区块链研习社

Cosmos-- 四.客户端 -- 6.规范

2019-02-27  本文已影响6人  糙米薏仁汤

cosmos主网即将上线,对文档做了大量更新。特地翻译了一下,方便小伙伴们阅览, 之后会持续更新

第四章客户端:

  1. 客户端
  2. CLI
  3. 服务提供商
  4. 轻客户端概览
  5. 开始
  6. 规范

规范

该规范描述了如何实现LCD。LCD支持模块化API。目前,还只支持ICS0(Tendermint API),ICS1(Key API)和ICS20(Token API)。以后,如有需要的话可以包含更多API。

构建并验证ABCI状态证明

众所周知,基于cosmos-sdk的应用程序的存储包含多个子存储。每个子存储由IAVL存储实现。这些子存储由简单的Merkle树组织。要构建树,我们需要从这些子存储中提取名称,高度和存储根哈希以构建一组简易的Merkle叶节点,然后计算从叶节点到根的哈希。简易Merkle树的根哈希是AppHash,它将包含在区块头中。

simpleMerkleTree.35a69100.png

正如我们在LCD信任传播中所讨论的,可以通过检查可信验证人集合的投票权来验证AppHash。在这里,我们只需要建立从ABCI状态到AppHash的证明。证明包含两部分:

IAVL证明

证明有两种类型:存在证明和不存在证明。如果要查询键值是否存在于IAVL存储中,则它返回键值及其存在证明。另一方面,如果键值不存在,那么它只返回不存在证明,这可以证明键值肯定不存在。

IAVL存在证明
type CommitID struct {
    Version int64
    Hash    []byte
}

type storeCore struct {
    CommitID CommitID
}

type MultiStoreCommitID struct {
    Name string
    Core storeCore
}

type proofInnerNode struct {
    Height  int8
    Size    int64
    Version int64
    Left    []byte
    Right   []byte
}

type KeyExistsProof struct {
    MultiStoreCommitInfo []MultiStoreCommitID //All substore commitIDs
    StoreName string //Current substore name
    Height  int64 //The commit height of current substore
    RootHash cmn.HexBytes //The root hash of this IAVL tree
    Version  int64 //The version of the key-value in this IAVL tree
    InnerNodes []proofInnerNode //The path from to root node to key-value leaf node
}

存在证据的数据结构如上所示。构建和验证存在证明的过程如下所示:

existProof.16d0e856.png

构建证明的步骤:

验证证明的步骤:

IAVL不存在证明

众所周知,所有IAVL叶子节点都按每个叶子节点的key排序。因此,我们可以计算此IAVL树的整个key集合中目标key的位置。如下图所示,我们可以找到左key和右key。如果我们可以证明左key和右key肯定存在,并且它们是相邻的节点。因此目标key肯定不存在。

absence1.9fe56931.png

如果目标key大于最右边的叶子节点的或小于最左边节点的key,则目标key肯定不存在。

absence2.d0d2b33b.png absence3.c3f6007e.png
type proofLeafNode struct {
    KeyBytes   cmn.HexBytes
    ValueBytes cmn.HexBytes
    Version    int64
}

type pathWithNode struct {
    InnerNodes []proofInnerNode
    Node proofLeafNode
}

type KeyAbsentProof struct {
    MultiStoreCommitInfo []MultiStoreCommitID
    StoreName string
    Height  int64
    RootHash cmn.HexBytes
    Left  *pathWithNode // Proof the left key exist
    Right *pathWithNode  //Proof the right key exist
}

以上是不存在证明的数据结构。构建证明的步骤:

验证证明的步骤:

针对AppHash的子存储的证明

在验证了IAVL证明之后,我们就可以开始验证针对AppHash的子证明。首先,遍历MultiStoreCommitInfo并通过证明StoreName找到子存储的commitID。验证commitID中的哈希是否等于证明的RootHash。如果没有,证明无效。然后通过子存储的name的哈希对子存储的commitInfo数组进行排序。最后,使用所有子存储的commitInfo数组构建简单的Merkle树,并验证Merkle根哈希值是否等于appHash。

func SimpleHashFromTwoHashes(left []byte, right []byte) []byte {
    var hasher = ripemd160.New()

    err := encodeByteSlice(hasher, left)
    if err != nil {
        panic(err)
    }

    err = encodeByteSlice(hasher, right)
    if err != nil {
        panic(err)
    }

    return hasher.Sum(nil)
}

func SimpleHashFromHashes(hashes [][]byte) []byte {
    // Recursive impl.
    switch len(hashes) {
        case 0:
            return nil
        case 1:
            return hashes[0]
        default:
            left := SimpleHashFromHashes(hashes[:(len(hashes)+1)/2])
            right := SimpleHashFromHashes(hashes[(len(hashes)+1)/2:])
            return SimpleHashFromTwoHashes(left, right)
    }
}

验证验证人集合的区块头

以上部分经常引用appHash。但值得信赖的appHash来自哪里?实际上,appHash存在于块头中,因此接下来我们需要验证特定高度的LCD可信验证人集合的区块头。验证流程如下所示:

commitValidation.dd75cbe3.png

当可信验证人集合与区块头不匹配时,我们需要尝试将可信验证人集合更新为此高度区块的验证人集合。LCD有一个规则,即每个验证人集合的变化不应超过1/3投票权。如果目标验证人集合的投票权变化超过1/3,则与可信验证人集合进行比较。我们必须验证在目标验证人集合之前是否存在隐藏的验证人集合变动。只有当所有验证人集合变更都遵循此规则时,才能完成验证人集合的更新。

例如:

updateValidatorToHeight.6ff55d6c.png
上一篇 下一篇

猜你喜欢

热点阅读