无链之链:R3 Corda带来的新视角(一):基本概念与模型

来源:互联网 发布:欠淘宝贷款 编辑:程序博客网 时间:2024/06/05 02:36



王玮

渡鸦区块链专栏作者




著名的金融领域分布式账本R3项目由于有众多金融机构的参与和支持,并且获得了数千万美元的融资,自宣布之日起就受到整个区块链生态环境的瞩目。


从公布的一些新闻稿、白皮书中,人们已经了解到:R3的最大特点之一,就是一个没有区块链的“类区块链”系统,但是具体实现方案是什么,与区块链相关的系统对比又有什么特色,还是一个未知数。


随着R3的基础设施Corda项目在2016年11月30日宣布开源,笔者在第一时间对其技术白皮书、在线文档和源代码做了初步的阅读和分析。


我们看到Corda的交易验证、共识机制等特性,采用了基于Notary(公证员)的模式。同时,为了服务于现实世界中的企业,Corda还具有很多与外部世界通讯的能力,例如:汇率、股票价格等信息的接收,可以通过一个叫做Oracle(先知)的角色来实现。


总之,与此类似的设计还有不少,这一系列选择都是R3根据自身定位有意为之。R3 Corda是一个基于半信任环境的、服务于现实世界金融活动的分布式账本,同时满足信息适度可见和高性能两个核心特性。


Corda区别于其他“类区块链”系统的另一个重要特点,就是系统本身基于一个小众语言Kotlin来开发,运行在JVM之上。


从实现层面来看,Corda有着鲜明的Java生态环境特点,例如:其节点使用的通讯、存储技术都是Java领域普遍采用的开源框架组合模型,相信这一点使得Corda非常适合企业使用,同时其自身开发成本也很低。此外,Corda中的合约(contract)以及Dapp应用,原则上是可以基于JVM上的任何语言来开发的,在应用开发者层面,一定程度上减小了kotlin小众化问题的影响。


除此之外,Corda作为较新的类区块链平台,还有很多令人关注的特性,本文将对其与区块链概念相关的各方面特性做一个概览,以便读者较为快速地了解这一著名的金融领域分布式账本。



基本概念与模型


去中心化数据库(Decentralized Database)

在技术层面上,Corda的定位是一个“去中心化数据库”,这一点对于理解Corda的设计和实现理念是非常重要的。


首先,在概念层面,去中心化数据库与分布式数据库有着重要的区别:分布式数据库仍然是一个中心化的系统,其服务目标是接收客户端的消息来存储数据,重点关注的是解决系统内部各个节点之间数据同步的问题。去中心化数据库,则是相互独立的参与方各自的私有数据库,在一定前提条件下同步某一方面的数据,如果参与方之间不完全的互相信任,则无法使用分布式系统中标准的数据同步算法。因此,两类系统的关注点、设计和实现模式大相径庭。


其次,在实现层面,去中心化数据库并不限于一种特定的技术:区块链这一随着比特币诞生的基础设施,可以认为是去中心化数据库的一种实现方式,也是现阶段获得最多认可的一种方式,但不是唯一的方式。从这个角度讲,Corda通过一系列的设计,给我们带来了去中心化数据库的另一种实现方案,这就是Corda系统的核心价值,一旦为人们所接受,必然会在“类区块链”生态系统中占有一席之地。


因此,Corda系统中最基本的概念、数据结构、算法和实现方式,在技术层面都是围绕“去中心化数据库”这一概念来完成的。


状态(State)与UTXO

状态是Corda网络中最基本的概念,我们可以理解状态就是“系统中的事实”,例如:“Alice拥有5000美元”,这就是一个状态。Corda系统的状态设计是基于交易的,也就是说只有一个有效交易的输出才是系统认可的有效状态,这实际上就是人们已经比较了解的UTXO模型。


系统中还可以有另一个状态,就是“Alice拥有3000美元”,这是Alice参与的另一个交易产生的输出。假定系统中不再有任何Alice拥有某种资产的事实存在的话,那么从现实世界的角度看,可以认为Alice拥有8000美元。但是,Corda系统中并不存在“Alice拥有8000美元”这一事实,只有前述两个事实。熟悉“类区块链”系统的人都知道,在一个UTXO模型的系统中,Alice只有跟自己做一次交易,以前述两个状态作为输入,才能产生一个新的“Alice拥有8000”美元的状态。与此同时,前两个状态在系统中也就失效了。


与基于交易的状态模型对应的,是所谓基于账户的状态设计。也就是说,每一个交易会形成对账户状态的改变,就像银行存款账户的“余额”会随着该账户的每一次交易而变化。以太坊等区块链系统,采用的就是基于账户的模型(可能有人知道,Serenity声明也支持建立一个UTXO模型的代币系统,只在这里顺便提一句,就不展开了)。这两种模型的优劣,有相关的文章进行讨论,不是本文的重点。笔者的观点是,它们之间的差异与面向对象(O-O)的模式和函数式(functional)的模式之间的差异可以类比。


值得指出的是:采用了UTXO模型的系统,其交易之间实际上就有一个“链式结构”:一个交易的输出,成为另一个交易的输入,交易与交易之间就通过这个方式被串起来了。这样的链式结构,实际上是一个有向无环图(DAG),读者可以自行验证。同时,由于Corda系统的数据不是全局的,所以这样的“链”在系统中会存在多个,相互之间没有连接。因此,Corda系统中虽然没有“区块链”,但是仍然有“交易链”,这也就是笔者称Corda为“无链之链”的原因。


交易(Transaction)

交易就是状态转换的过程,简单地说是{输入状态、交易指令、输出状态}组成的元组,其中输入、输出都可以是一个状态列表。


此外,交易还包括其他一些要素,如:附件、时间戳、各种签名以及为采用硬件加密的目的而使用的文字摘要(summeries),比较重要的部分都会在本文中讨论到。这一定义与其他“类区块链”系统中的交易定义区别不大,最主要的差异在于“交易指令”(command)这一概念,它描述的是这个交易具体是做什么的。


Corda的设计目标是对现实世界中各种交易类型进行支撑,因此要具有描述交易实际执行动作的能力,例如:转账、存入/提现、开票/兑付,诸如此类,所以要引入command这一概念。


当然,这些交易动作只需要交易参与方事先约定就可以了,他们可以约定什么值表示什么含义,因此指令本身的具体值并不重要。Corda交易指令设计的关键要点是,指令必须包括有权作出这个指令的全部参与方的公钥用于后续的签名验证,并且允许交易的合约代码对此进行检查。比如说,资金转账的指令必须是某个银行才能执行,而开具一张承兑汇票的指令则可能需要开票方、承兑方都签署才能生效,这样一来接收这张汇票的一方,就可以通过事先编写的合约代码来实现这一检查。 


有了指令机制,交易的合法性验证过程也更加清晰了:一个交易的全部指令所列出的所有参与方,就是一个交易需要签名的所有参与方。


这是个充分必要条件,很好地解决了一个问题:交易到底需要验证哪些签名才被认为是有效的。同时值得提出的是,Corda的合约验证流程实现了合约与哈希算法之间的解耦——合约代码只需要判断事先约定的参与方的公钥是否都包含在此次交易的command当中,而对交易的全部签名的有效性(是否与这些公钥匹配)进行验证的工作留给Corda系统来做。这是Corda设计的一个特色,可以简化合约代码的开发和部署/升级工作,例如:一个合约对应的多次交易过程中系统的加密算法进行了升级,智能合约的代码是不需要改变的,这一点相对于比特币而言有一定优势。 


除了command这一关键概念之外,Corda系统中交易还有很多特性,这里列出几个与Corda设计目标相匹配特点:

为了适应多方复杂交易的机制,Corda引入了联合公钥(Composite keys)的概念,系统中所说的需要keys的地方,都是指一个Composite key的结构。


联合公钥是一个树状结构,叶节点表示来自一个参与方的一个公钥,而上层节点代表联合权重,用于表示必须有满足权重值条件的参与方签名才能认为该节点有效。例如:一个上层节点的权重为3,则意味着其下面节点必须有3个有效签名,这个节点才算有效。反过来说,一个权重为3的节点下面有5个参与方的公钥,也只需要3个签名有效,这个节点就有效。通过层层判断,到根节点形成一个组合条件,最终判断全部签名的总体有效性。联合公钥的概念如图1所示。 


Corda的交易具有“半匿名”的能力,每一个状态都有他所属的参与方信息(party),这个信息包含两个“字段”:公钥和标识。只有公钥字段是任何时刻都必须有值的,一个新交易创建或者从磁盘上反序列化到内存中的时候,可以根据交易的参与方当前提供的身份来填充标识字段,这样就实现了交易参与者根据自身需要(和可接受的程度)来决定每一笔交易是实名的还是匿名的。


另外,交易发送给Notary等节点进行签名时,也不需要传输标识字段,这样一来,即使一个交易本身是实名的,从全网的角度看仍然可以做到半匿名。


另外需要提及的一点,Corda中交易的类型有两种:普通交易和Notary变更交易。由于Notary概念还没有介绍,这里就不详细展开了,只要说明一件事:这两种交易类型的区别主要在验证流程,输入输出类型都是一样的,因而Corda的交易概念定义是唯一的。


合约(Contract)

合约就是交易双方事先达成的契约。从合约的角度看,交易其实就是它的一次执行过程,因此合约对交易有约束性,并且一个合约可以多次执行,也就是多个交易可以对应一个合约。


Corda的合约也就是我们常说的“智能合约”,本质上是一段代码,在JVM的体系中,就是一个类。合约都需要实现Contract这个Interface,这个接口有一个函数和一个属性:方法是verify,用于验证交易的合法性。这个函数接收TransactionForContract类型的参数,其中的关键点在于这个类型的构造函数的参数都是不可变参数类型,因此保证了Corda的合约都是“纯函数”——只能对交易起到验证作用,无法对被验证的交易产生任何副作用。


Contract的唯一属性:legalContractReference,是一个SecureHash类型的数据,用来存储现实世界中真实合约的标识。我们很容易想到:可以用这个值来存储合约文件实际内容的哈希值,用来保证对应合约内容的唯一性,很明显这是Corda系统与真实世界建立关系的一个连接点。


通过这样的结构,contract实现了它应该具有的两个能力:描述现实世界的合约,并且对根据这个合约进行的任何交易进行验证。从技术实现上来看,Corda的合约就是一个Java的class文件,可以被JVM执行,从而开发者可以使用JVM上的各种语言进行开发,合约代码中原则上也可以调用很多JVM上已有的类库、代码,这也是Corda的一大优势。在交易执行过程中,这个class文件必须作为交易的附件,是交易的输入条件之一,被系统加载并执行其verify函数。 


这里需要再次强调的一点是:Corda的智能合约是“纯函数”,这一点和比特币类似,总体上就是说智能合约无法改变系统/交易的状态,即使无数次执行智能合约的代码,最终产生的结果都是一样的,系统状态也没有任何改变。


Oracle

Corda的设计理念之一就是要和现实世界发生联系,这种联系的能力前面已经看到了很多,Oracle则是这个理念的另一重要体现,这也是为什么笔者认为应该将其放在基本概念的范围来讲。股票价格、外汇牌价、银行利率,甚至一些非标准的信息(比如某家企业倒闭),都是“外部世界”发生的事实,而交易的过程和结果的验证,往往需要依赖这些信息。


Oracle(先知)就是这样一个角色——一个受信任的公共服务,用来将现实世界中的事实“注入”到Corda网络中,使之可以成为交易的一个输入项。


具体实现方面,Corda将Oracle的行为模式设计成为对每一个交易进行事实的注入,而不是对整个系统进行注入。这样的设计有两方面的合理性,一方面是作为去中心化的数据库,恐怕也没有一个地方来登记所谓全局的信息了;另一方面从经济的角度讲,如果信息是全局的,一旦某个参与方获得了,就可以和其他人共享,Oracle就只有在发布信息的那个时刻才能获得报酬,经济利益方面没有保障将使得没有人愿意去承担这样的角色。因此,Oracle在每个交易中签署相应的内容,也成为Corda系统考虑现实世界经济活动特点的另一体现。


Oracle对整个交易进行签名的实现还带来了Corda当中另一个有普遍意义的概念:transaction tear-off,意思是说要把交易发给一个角色时,可以把不需要他知道的具体数据从发送的内容中删除,却仍然不影响他对整个交易签名。


有了这个机制,就可以实现交易的隐私保护。那么,没有交易的全部数据,怎么实现对整个交易进行签名呢?为此,Corda将交易的签名结构做成一棵Merkle Tree,从而可以实现将一个保留了必要签名的分支发送给Oracle,使他仍然能按照签名结构完成对整个交易的签名。很显然,这基本上借鉴了比特币交易的签名实现机制,唯一不同的是,比特币用这种机制来节约磁盘空间的占用,而Corda用他来实现交易的隐私保护。


未完待续……


作者简介: 王玮  (wangwei@wecite.com.cn)

“中关村20周年突出贡献奖”获得者,北京微志科技有限公司创始人。主持过世界上最大的基于开放平台和分布式技术的银行账务系统的设计与开发,曾任国家“核高基”国产化中间件应用示范项目副组长等。目前从事区块链技术在金融等领域应用的研究、开发和推广工作。 文章首发于《程序员》杂志,版权归《程序员》杂志所有。




转载/投稿请扫描以下二维码联系

阅读全文
0 0
原创粉丝点击