cosmos IBC

引自:https://github.com/cosmos/cosmos/blob/master/WHITEPAPER.md#transaction-types

IBC Packet Delivery Acknowledgement

There are several reasons why a sender may want the acknowledgement of delivery of a packet by the receiving chain. For example, the sender may not know the status of the destination chain, if it is expected to be faulty. Or, the sender may want to impose a timeout on the packet (with the MaxHeight packet field), while any destination chain may suffer from a denial-of-service attack with a sudden spike in the number of incoming packets.

In these cases, the sender can require delivery acknowledgement by setting the initial packet status to AckPending. Then, it is the receiving chain's responsibility to confirm delivery by including an abbreviated IBCPacket in the app Merkle hash.

Figure of Zone1, Zone2, and Hub IBC with acknowledgement

First, an IBCBlockCommit and IBCPacketTx are posted on "Hub" that proves the existence of an IBCPacket on "Zone1". Say that IBCPacketTx has the following value:

  • FromChainID: "Zone1"
  • FromBlockHeight: 100 (say)
  • Packet: an IBCPacket:
    • Header: an IBCPacketHeader:
      • SrcChainID: "Zone1"
      • DstChainID: "Zone2"
      • Number: 200 (say)
      • StatusAckPending
      • Type: "coin"
      • MaxHeight: 350 (say "Hub" is currently at height 300)
    • Payload: <The bytes of a "coin" payload>

Next, an IBCBlockCommit and IBCPacketTx are posted on "Zone2" that proves the existence of an IBCPacket on "Hub". Say that IBCPacketTx has the following value:

  • FromChainID: "Hub"
  • FromBlockHeight: 300
  • Packet: an IBCPacket:
    • Header: an IBCPacketHeader:
      • SrcChainID: "Zone1"
      • DstChainID: "Zone2"
      • Number: 200
      • StatusAckPending
      • Type: "coin"
      • MaxHeight: 350
    • Payload: <The same bytes of a "coin" payload>

Next, "Zone2" must include in its app-hash an abbreviated packet that shows the new status of AckSent. An IBCBlockCommitand IBCPacketTx are posted back on "Hub" that proves the existence of an abbreviated IBCPacket on "Zone2". Say that IBCPacketTx has the following value:

  • FromChainID: "Zone2"
  • FromBlockHeight: 400 (say)
  • Packet: an IBCPacket:
    • Header: an IBCPacketHeader:
      • SrcChainID: "Zone1"
      • DstChainID: "Zone2"
      • Number: 200
      • StatusAckSent
      • Type: "coin"
      • MaxHeight: 350
    • PayloadHash: <The hash bytes of the same "coin" payload>

Finally, "Hub" must update the status of the packet from AckPending to AckReceived. Evidence of this new finalized status should go back to "Zone2". Say that IBCPacketTx has the following value:

  • FromChainID: "Hub"
  • FromBlockHeight: 301
  • Packet: an IBCPacket:
    • Header: an IBCPacketHeader:
      • SrcChainID: "Zone1"
      • DstChainID: "Zone2"
      • Number: 200
      • StatusAckReceived
      • Type: "coin"
      • MaxHeight: 350
    • PayloadHash: <The hash bytes of the same "coin" payload>

Meanwhile, "Zone1" may optimistically assume successful delivery of a "coin" packet unless evidence to the contrary is proven on "Hub". In the example above, if "Hub" had not received an AckSent status from "Zone2" by block 350, it would have set the status automatically to Timeout. This evidence of a timeout can get posted back on "Zone1", and any tokens can be returned.

Figure of Zone1, Zone2, and Hub IBC with acknowledgement and timeout

Merkle Tree & Proof Specification

There are two types of Merkle trees supported in the Tendermint/Cosmos ecosystem: The Simple Tree, and the IAVL+ Tree.

Simple Tree

The Simple Tree is a Merkle tree for a static list of elements. If the number of items is not a power of two, some leaves will be at different levels. Simple Tree tries to keep both sides of the tree the same height, but the left may be one greater. This Merkle tree is used to Merkle-ize the transactions of a block, and the top level elements of the application state root.

                *
               / 
             /     
           /         
         /             
        *               *
       /              / 
      /              /   
     /              /     
    *       *       *       h6
   /      /      / 
  h0  h1  h2  h3  h4  h5

  A SimpleTree with 7 elements

IAVL+ Tree

The purpose of the IAVL+ data structure is to provide persistent storage for key-value pairs in the application state such that a deterministic Merkle root hash can be computed efficiently. The tree is balanced using a variant of the AVL algorithm, and all operations are O(log(n)).

In an AVL tree, the heights of the two child subtrees of any node differ by at most one. Whenever this condition is violated upon an update, the tree is rebalanced by creating O(log(n)) new nodes that point to unmodified nodes of the old tree. In the original AVL algorithm, inner nodes can also hold key-value pairs. The AVL+ algorithm (note the plus) modifies the AVL algorithm to keep all values on leaf nodes, while only using branch-nodes to store keys. This simplifies the algorithm while keeping the merkle hash trail short.

The AVL+ Tree is analogous to Ethereum's Patricia tries. There are tradeoffs. Keys do not need to be hashed prior to insertion in IAVL+ trees, so this provides faster ordered iteration in the key space which may benefit some applications. The logic is simpler to implement, requiring only two types of nodes -- inner nodes and leaf nodes. The Merkle proof is on average shorter, being a balanced binary tree. On the other hand, the Merkle root of an IAVL+ tree depends on the order of updates.

We will support additional efficient Merkle trees, such as Ethereum's Patricia Trie when the binary variant becomes available.

Transaction Types

In the canonical implementation, transactions are streamed to the Cosmos hub application via the ABCI interface.

The Cosmos Hub will accept a number of primary transaction types, including SendTxBondTxUnbondTxReportHackTxSlashTxBurnAtomTxProposalCreateTx, and ProposalVoteTx, which are fairly self-explanatory and will be documented in a future revision of this paper. Here we document the two primary transaction types for IBC: IBCBlockCommitTx and IBCPacketTx.

 

IBCBlockCommitTx

An IBCBlockCommitTx transaction is composed of:

  • ChainID (string): The ID of the blockchain
  • BlockHash ([]byte): The block-hash bytes, the Merkle root which includes the app-hash
  • BlockPartsHeader (PartSetHeader): The block part-set header bytes, only needed to verify vote signatures
  • BlockHeight (int): The height of the commit
  • BlockRound (int): The round of the commit
  • Commit ([]Vote): The >⅔ Tendermint Precommit votes that comprise a block commit
  • ValidatorsHash ([]byte): A Merkle-tree root hash of the new validator set
  • ValidatorsHashProof (SimpleProof): A SimpleTree Merkle-proof for proving the ValidatorsHash against the BlockHash
  • AppHash ([]byte): A IAVLTree Merkle-tree root hash of the application state
  • AppHashProof (SimpleProof): A SimpleTree Merkle-proof for proving the AppHash against the BlockHash

IBCPacketTx

An IBCPacket is composed of:

  • Header (IBCPacketHeader): The packet header
  • Payload ([]byte): The bytes of the packet payload. Optional
  • PayloadHash ([]byte): The hash for the bytes of the packet. Optional

Either one of Payload or PayloadHash must be present. The hash of an IBCPacket is a simple Merkle root of the two items, Header and Payload. An IBCPacket without the full payload is called an abbreviated packet.

An IBCPacketHeader is composed of:

  • SrcChainID (string): The source blockchain ID
  • DstChainID (string): The destination blockchain ID
  • Number (int): A unique number for all packets
  • Status (enum): Can be one of AckPendingAckSentAckReceivedNoAck, or Timeout
  • Type (string): The types are application-dependent. Cosmos reserves the "coin" packet type
  • MaxHeight (int): If status is not NoAckWanted or AckReceived by this height, status becomes TimeoutOptional

An IBCPacketTx transaction is composed of:

  • FromChainID (string): The ID of the blockchain which is providing this packet; not necessarily the source
  • FromBlockHeight (int): The blockchain height in which the following packet is included (Merkle-ized) in the block-hash of the source chain
  • Packet (IBCPacket): A packet of data, whose status may be one of AckPendingAckSentAckReceivedNoAck, or Timeout
  • PacketProof (IAVLProof): A IAVLTree Merkle-proof for proving the packet's hash against the AppHash of the source chain at given height

The sequence for sending a packet from "Zone1" to "Zone2" through the "Hub" is depicted in {Figure X}. First, an IBCPacketTx proves to "Hub" that the packet is included in the app-state of "Zone1". Then, another IBCPacketTx proves to "Zone2" that the packet is included in the app-state of "Hub". During this procedure, the IBCPacket fields are identical: the SrcChainID is always "Zone1", and the DstChainID is always "Zone2".

The PacketProof must have the correct Merkle-proof path, as follows:

IBC/<SrcChainID>/<DstChainID>/<Number>

When "Zone1" wants to send a packet to "Zone2" through "Hub", the IBCPacket data are identical whether the packet is Merkle-ized on "Zone1", the "Hub", or "Zone2". The only mutable field is Status for tracking delivery.

IBC协议

引自:https://zhuanlan.zhihu.com/p/42693285

IBC协议是针对Cosmos网络设计的,依赖其及时最终性的特点,用于Hub与Zone之间消息传递。IBC协议中设计了两个消息:

  • IBCBlockCommitTx:发送方所在区块链的最新的区块信息。
  • IBCPacketTx:跨链交易本身的信息,及其在发送方链中被打包的区块信息。

但有了消息的传递,接收链如何校验信任消息呢?

在IBC协议设计里,两个链建立连接之前需要进行彼此注册,有两个作用:

1、保存对方链验证者集合以及Merkle证明的算法,这样接收链才能确保消息的正确性和来源的可靠性。

2、为对方链创建两个可靠队列,一个队列存放所以对方链的消息(outgoing),一个队列存放来自对方链的消息(incoming)。

我们以chain1中用户User A转100mycoin 给test-hub用户User B为例看看IBC整个的工作流程如下(基于目前IBC实现代码):

整个工作流程可以分为三个阶段:

  1. User A向chain1提交跨链交易,chain1执行该交易,并将交易存入outgoing队列。
  2. relayer从chain1中对应test-hub的outgoing消息队列取出跨链交易,提交到test-hub。
  3. test-hub执行交易,放入incoming消息队列。

PegZone

基于cosmos-sdk开发的区块链能够轻松满足实时最终性,然而现存的Bitcoin和Ethereum这类使用POW共识的区块链并不具备此特点,只能属于概率最终性,无法防止区块链的回滚。对于这类链,团队采用PegZone方案来解决。

PegZone本身其实是一条代理链,实时跟踪原始链的状态,通过设定一个安全阀值,等待原始链区块增长数达到安全阀值时就认为原始链的状态达到了伪实时最终性(回滚概率小),这点和轻客户端钱包验证是相同的原理,例如比特币安全阀值通常设置为6,以太坊安全阀值可以设置为20或者100。而PegZone本身具备实时最终性,就可以通过IBC与Hub相连,从而实现跨链。

接下来还是用例子来说明下,以Ethereum为例来看,有兴趣的朋友可参考Github上的cosmos/Peggy项目。示意图如下:

 

上图我们可以看出PegZone可以分为5个部分:

    1. Smart Contract:资产托管的角色,保管以太坊中的代币和Cosmos中的代币。主要提供了lock、unlock、mint、burn四个方法。
    2. Witness:是一个以太坊全节点,监听以太坊合约的event,并等待100个区块产生后,封装WitnessTx提交到PegZone中来证明在以太坊内状态更改。
    3. PegZone:PegZone是基于Tendermint的区块链,负责维护用户的账户信息,允许用户之间资产的转移,并提供交易查询。
    4. Signer:使用secp256k1对交易进行签名,以便签名能够高效的被智能合约验证,对应于智能合约的校验者公钥集合。
    5. Relayer: 中继器负责交易转发。将所有Signer签名后的SignTx转发到smart contract中。
原文地址:https://www.cnblogs.com/yunlion/p/10442413.html