1.没有区块链,没有挖矿,是一个permissioned network。
2.没有广播,是点对点的消息交流方式。
3.用UTXO模型来记录状态(类似比特币)。
4.基于JVM的平台,使用Kotlin编写(可以用Java,Clojure等)。
Corda网络是可验证的P2P网络,其中每个节点都是托管Corda服务并执行称为CorDapps的应用程序的JVM run-time environment。
• Corda网络是全连接的图
• 没有全球广播或gossip网络
• 通信仅在点对点的基础上进行
• 数据是在need-to-now的基础上共享的
• peer通过TLS使用AMQP / 1.0进行通信
• 图的边表示通信的可能性,而不是持久性连接
• 类似电子邮件和SMTP
网络中主要有下面几种成员:
Doorman(门卫):执行有关信息节点在被允许进入网络之前必须提供的规则。 如果同意,则使用根权限签名的TLS证书对节点的标识进行认证。
要加入网络,节点必须联系Doorman并提供所需信息。 如果通过验证,节点将从网络许可服务接收一个 root-authority-signed TLS 证书,(一个 TLS 证书和一个签名证书(signing certificate)作为 well know identity)。这个证书会在今后同其他节点的沟通中作为该节点的身份证明被使用。
Nodes(节点):具有运行Corda的唯一网络标识的JVM run-time,具有两个接口:网络层(与其他节点交互)和RPC(与节点所有者交互)。
Network Map Service(网络地图服务):发布IP地址,通过该地址可以访问所有节点以及节点提供的证书和服务。
Notary(公证人):对账本更新验证唯一性和可能性。
Oracles:众所周知的服务,如果他们陈述事实并且该事实被认为是信任则签署交易
(使用Apache Artemis嵌入式消息服务的消息代理来实现日志关系型数据库存储数据)
其他概念:
Network Map Service:
发布可以通过其访问网络上每个节点的IP地址,这些节点的身份证书和它们提供的服务
(用于负载均衡和网络可视化。地图是一种可以被缓存并分发到全网络的一种文档。因此地图不用要求高可用性:如果地图服务处于离线状态,新接入节点就没法注册到该服务,已接入的节点也没法分发相关状态变化出去,不过,其他的会一切照常进行。Network map类似于微服务中的 service discovery,Corda中节点的互相发现并不是通过广播的方式发生,而是通过注册Network map获取其它节点的信息,进而找到对方)
Identity:
Corda的Identity可以代表组织的合法身份(用于交易中的各方)和网络服务的标识(用于提供与交易相关的服务)
identity分为well konwn(众所周知的)或confidential(保密的),众所周知的身份是法人实体或服务的证书。 此证书将在网络地图服务中发布,供任何人访问。
机密身份仅发布给使用identity参与交易的人。
状态(state)是不可变对象,表示在特定时间点一个或多个Corda节点已知的事实。下图表示一个代表Alice欠了Bob £10的state。
state是通过将当前状态标记为历史状态并创建新状态来演变的。下图表示一个state的序列。
States 可以包含任何的数据,这就允许了它可以代表任何的类型的事实(比如股票,借款,KYC 数据,身份数据等等)。
state图中,右边是数据本身,例如图中描述了 Alice 欠 Bob 的10美元的情况;左上是这条数据所关联的 contract;左下是 participants,Corda 不会在每个节点上记录每笔交易,participants 表示哪些节点需要记录这条 state 数据。
state 是不可篡改的,当真实世界中的事实发生变化时,Corda 会将已经成为历史的 state 标记为 consumed。
Corda 网络中的每一个节点都维护着一个 vault,它是一个关系型数据库,其中跟踪了所有 states 的当前以及历史的 states 数据,当然每个节点只能够看到跟它有关的数据。如下图所示。
UTXO模型中,交易处理的基本单位是一个交易记录,任何一个交易的输入都是某一个交易的输出。UTXO的消费是不会掰开花的,只能拿出合适的一个全花出去,然后接受对方找零(其实不是对方找零,而且比特币交易系统自动为我们做的找零操作,UTXO接收方(目标地址)是感知不到的)。
所有的交易输入都必须来自于前面一个或者几个交易的UTXO输出,并且每一笔的交易支出总额等于交易收入总额。
举个例子:
operations:
(1)A给X支付一笔5个比特币;
(2)B又给X支付一笔2个比特币;
(3)C给X支付一笔1个比特币;
(4)X给其他某个人转出支付一笔3.5个比特币。
results:
(1)之后,X钱包里有一笔大小为5的UTXO收入交易记录,共一笔,净UTXO:5
(2)之后,X钱包里有一笔大小为5的和一笔大小为2的UTXO收入交易记录,共两笔,净UTXO:7
(3)之后,X钱包里有一笔大小为5的,一笔大小为2的和一笔大小为1的UTXO收入交易记录,共三笔,净UTXO:8
(4)之后,X的钱包里基于(3)的基础上,新增一笔支出大小为5个UTXO,然后新增一笔大小为1.5的收入交易记录。净UTXO:3–>4.5
Corda 使用 UTXO模型来使账本上的每条 state 都不可更改。对于账本上数据的变更都是通过使用 transaction 的方式来做的,就是将0条或多条已经存在的 input state 的记录变为历史记录,然后再新增0条或多条新的 output state。
一笔交易如下图所示:
注意:
仅仅验证提议的交易本身是不够的。我们还必须验证导致创建交易输入的交易链中的每个交易。transaction 中包含的 input 应该是在账本中已经存在的,应该是前一个 transaction 添加进去的 output。所以我们需要在新的 transaction 中引用这些已经存在的记录,然后把他们在账本中消费掉(consume,本质上是设置为历史记录)
这些 Input state 的引用包含两部分:创建这个 input 的 transaction 的 hash 和这个 input 所指的前一个 transaction 带来的 output state 在 output list 中的位置或者说索引值。
一个交易链的例子:
为了映射自然世界中各种复杂的多方交易,Corda中引入了“复合公钥”(composite-keys)。其中的公钥以树结构组织:所有的叶子节点就是各个参与方的key,指定了权重,上层节点则约定必须达到的加权阈值。
一个签名集合的有效性可以通过这样 的方式确认:从底往上行经这棵树,对其中所有具有有效签名的密钥的权重求和,并与阈值相比较。通过使用权重和阈值,可以编码多种多样的情况,包括 使用 AND 和 OR 的布尔表达式。
比如下面这个例子中,三人的公钥权重默认都是1,那么整个command有效的条件是:“alice和bob都要签名”或“只要charlie签名”。
合约有效性是指:
合约的限制
交易是否accept仅仅基于输入的transaction的内容:检查 inputs,outputs,commands 的数量,时间,附件等。
contract 来判断 transaction 是否有效是在一个具有确定性结果的 sandbox 中进行的。因为 contract 没有办法访问到外部的信息,它只能检查 transaction 自身的有效性,比如它不能够检查确认当前这个 transaction 是不是已经同其他相关方达成了共识取得了其他方的确认。
所以在各方提供最终的签名确认之前,各方应该对transaction 的内容进行检查来确定他们是否同意这个对账本的更新,即使这个 transaction 是合约有效(conceptual valid)的。任何一方是不会因为 transaction 是 contractually valid 就能够去提供签名。比如他们可能不愿意去提供一个巨额的借款,或者可能不会同意购买一个资产花费的钱的金额,虽然这些能够正常地通过 contract code 的验证,即 contractually valid,但是还是不会去接收这个 transaction 的。
Notary可以避免双花。一个网络中可以有多个 notaries,一个notary服务可以分布在不同节点上,每个 state 都会有一个指定的 notary,而且 notary 也只会去公正那些 input 指定它为公证人的 transaction。
每一个 notary 运行一个不同的共识算法(consensus algorithm)。
为了负载均衡,可以将交易负载分散到多个notary上,为整个平台提供更高的吞吐
为了降低延迟,可以通过选择物理上更接近交易方的notary,最大限度地减少延迟
当单个事务需要消耗具有不同指定公证人的几个状态时,或者当一个节点由于隐私或效率问题而倾向于为给定的交易使用不同的公证人时,会更换公证人。
注意,一个合法交易的所有输入必须基于同一个notary
Notary如何避免双花呢?看看下面的例子:
这个Oracle不是数据库的Oracle,而是一种服务。在许多情况下,交易的合约有效性取决于某些外部数据,例如当前的汇率。一个事实可以作为command的一部分包含在交易中。Oracle是一种服务,只有在包含的事实为真时才会对交易进行签名。
为了给一个 transaction 提供签名,Oracle 需要看的唯一的信息就是 transaction 里边的 command。向 Oracle 提供任何其他的信息会造成信息泄露。相类似的,一个 non-validating notary 只需要看到 transaction 的 input states 而不需要关注 contract code 是怎么写的,如果把 contract code 也发给了 non-validating notary 的话也会造成信息泄露。
因此用到了一个技术叫做Transaction tear-off
oracle需要看到的唯一信息是它们的嵌入的command。
同样,non-validating公证人只需要查看交易的输入状态。
使用Merkle树“tear off”oracle /公证人在向他们签名之前不需要看到的交易的任何部分。
Corda 使用了 flows 来步骤变得自动化。一个 flow 是一系列有顺序的步骤来告诉一个节点应该如何实现一个指定的账本更新,比如发行一个资产或者结算一笔交易。
Flow是Corda中控制参与节点如何更新State的自动化流程,它对如何获取交易方的签名进行了封装。一个标准的flow流程包括获取链上数据,创建一笔交易,自签名之后发送给对方方进行交易验证,再签名,最终在双方的账本上分别提交交易。Corda网络上的节点之间可能拥有数千个交易方和数十万个并发流。
一旦一个业务流程被封装在了一个 flow 中并且在节点中作为 CorDapp 的一部分被安装好之后,节点的 owner 可以在任何时间通过使用一个 RPC call 来告诉节点开始这个业务流程。Flow 将所有的网络,I/O 和并发问题都抽象了出来,这个节点 owner 就不需要关注这些了
节点上所有的动作都是发生在这些 flows 的上下文上的。与 contract 不同,flows 不是在 sandbox 里执行的,也就是说节点可以在执行一个 flow 的过程中来进行一些动作比如 networking,I/O 或者随机地使用一些资源。
下面是一个转账的Flow例子: