读书笔记基于cosmos最新的ibc规范ics的第2章client作的翻译

读书笔记是摘取ibc的文档ics协议中有趣的部分(可能也是关键部分)的翻译和源码对照, 意在理清ibc实现背后的原理和主要逻辑. 该repository作为本人读书笔记, 记录知识的获取, 以blog的形式记录下来. 该文库我会不断更新, 如果喜欢的话麻烦点一下star.

ics002-client

Motivation

Alice, a module on a machine, wants to introduce Bob, a second module on a second machine who Alice knows (and who knows Alice), to Carol, a third module on a third machine, who Alice knows but Bob does not. Alice must utilise an existing channel to Bob to communicate the canonically-serialisable validity predicate for Carol, with which Bob can then open a connection and channel so that Bob and Carol can talk directly. If necessary, Alice may also communicate to Carol the validity predicate for Bob, prior to Bob’s connection attempt, so that Carol knows to accept the incoming request.

alice作为一台机器上的一个module, 想要将bo(第二台机器上的第二个模块, bob和alice互相人事)介绍给carol(第三台机器上的第三个模块, carol仅alice认识). alice必须使用现存的与bob的通道来发送规范的串行序列, 序列用于证明carol的有效性. 通过这个序列bob能够与carol开启一个channel和connection介于此bob和carol可以直接通信. 如有必要alice同样可以与carol通信发送另一个规范的串行序列, 序列用于证明bob的有效性, 这个操作在bob尝试与carol建立链接之前, 因此carol会接受与bob传来的请求.

State machines implementing the IBC protocol can support any number of client types, and each client type can be instantiated with different initial consensus states in order to track different consensus instances. In order to establish a connection between two machines (see ICS 3), the machines must each support the client type corresponding to the other machine’s consensus algorithm.

实现IBC协议的状态机可以支持任意的客户端的成员, 并且每一种客户端都可以被不同的初始共识状态初始化以用来追踪不同共识的实例. 为了在两个机器集群间建立connection连接(ICS 3), 一方机器集群必须支持另一方拥有不同共识算法的机器集群对应的客户端.

Consensus is a Header generating function which takes the previous ConsensusState with the messages and returns the result.

type Consensus = (ConsensusState, [Message]) => Header

这显然是跨链协议中两条链互相同步对方的关键操作, ConsensusState是以往收到的另一条链的状态, [Messge]数组为以往状态到当前状态间发生的交易, 通过这两个参数, 我们可以相信至少

该函数有详尽的函数解释, 大意为: 1.会验证Header.Commit中的签名, 但要求签名人在Old_ConsensusState的验证人集合中. 2.符合第一点的签名人的vote_power占据Old_ConsensusState验证人集合的vote_power总和的2/3以上(ps. 当前验证人以及Old_ConsensusState的验证人的vote_power的视图均依据Old_ConsensusState的时间点, 意味着当前验证人的当前vote_power并不会影响校验结果, 该方式显然是经验性的, 官方的解释也是为了light client可验证的需要, 在验证人集合以及验证人vote_power大幅度激变的情况下, ibc在该light client下无法实施, 但如果ibc交易的发生与ibc前置配置工作紧密进行, 第二点验证要求的满足是极大概率通过的, 从这个环节可以发现最大渎职行为会发生在light client第一个传送的ConsensusState的验证, 这或许需要多light client的分布式验证???[大雾]) VerifyFutureCommit()函数方能通过, 之后更新client的ConsensusState状态.

Proxy clients Proxy clients verify another (proxy) machine’s verification of the target machine, by including in the proof first a proof of the client state on the proxy machine, and then a secondary proof of the sub-state of the target machine with respect to the client state on the proxy machine. This allows the proxy client to avoid storing and tracking the consensus state of the target machine itself, at the cost of adding security assumptions of proxy machine correctness.

代理客户端: 代理客户端验证代理机器对于目标机器的验证, 通过一份证明, 该证明包括一份代理机器上的客户状态的证明, 另一份代理机器人的目标机器子状态对应的客户状态证明. 这允许代理客户端避免存储和跟踪目标机器的共识状态, 但这一切建立在增加代理机器的安全风险上面. 代理人也是ibc中关键中间人, 这段翻译我理解为代理客户端需要代理机器人本身的客户状态的有效性证明以及目标机器的客户状态在代理机器上的有效性证明, 猜测目标机器的客户端对于本地机器也是代理客户端与目标机器的关系, 那么代理机器的责任真是非常重大, 因为他可以做出伪造数据一类渎职行为.

Utilising past roots To avoid race conditions between client updates (which change the state root) and proof-carrying transactions in handshakes or packet receipt, many IBC handler functions allow the caller to specify a particular past root to reference, which is looked up by height. IBC handler functions which do this must ensure that they also perform any requisite checks on the height passed in by the caller to ensure logical correctness.

使用过去的roots: 为了避免client更新状态(区块高度增长, 会影响到根状态)和携带证明的交易握手过程或包接收过程之间存在的竞态, 很多IBC的处理函数会允许调用者指定特定高度的根状态作为参考. IBC处理函数必须确保他们对调用者传入的高度执行了必要的检查, 以保证逻辑的正确性.

Create Client的伪代码

function createClient(   id: Identifier,   clientType: ClientType,   consensusState: ConsensusState) {     abortTransactionUnless(validateClientIdentifier(id))     abortTransactionUnless(privateStore.get(clientStatePath(id)) === null)     abortSystemUnless(provableStore.get(clientTypePath(id)) === null)     clientState = clientType.initialize(consensusState)     privateStore.set(clientStatePath(id), clientState)     provableStore.set(clientTypePath(id), clientType) }

与源码实现的函数比较:

// CreateClient creates a new client state and populates it with a given consensus // state as defined in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#create func (k Keeper) CreateClient(     ctx sdk.Context, clientID string,     clientType exported.ClientType, consensusState exported.ConsensusState, ) (types.State, error) {     _, found := k.GetClientState(ctx, clientID)     if found {         return types.State{}, types.ErrClientExists(k.codespace, clientID)     }      _, found = k.GetClientType(ctx, clientID)     if found {         panic(fmt.Sprintf("consensus type is already defined for client %s", clientID))     }      clientState := k.initialize(ctx, clientID, consensusState)     k.SetVerifiedRoot(ctx, clientID, consensusState.GetHeight(), consensusState.GetRoot())     k.SetClientState(ctx, clientState)     k.SetClientType(ctx, clientID, clientType)     k.Logger(ctx).Info(fmt.Sprintf("client %s created at height %d", clientID, consensusState.GetHeight()))     return clientState, nil }

k.SetVerifiedRoot(ctx, clientID, consensusState.GetHeight(), consensusState.GetRoot())似乎未出现在伪代码中, 是不是忘了?

Update Client的伪代码

function updateClient(   id: Identifier, verifyMembership   header: Header) {     clientType = provableStore.get(clientTypePath(id))     abortTransactionUnless(clientType !== null)     clientState = privateStore.get(clientStatePath(id))     abortTransactionUnless(clientState !== null)     clientType.checkValidityAndUpdateState(clientState, header) }

源码实现:

// UpdateClient updates the consensus state and the state root from a provided header func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.Header) error {      clientType, found := k.GetClientType(ctx, clientID)     if !found {         return sdkerrors.Wrap(types.ErrClientTypeNotFound(k.codespace), "cannot update client")     }      // check that the header consensus matches the client one     if header.ClientType() != clientType {         return sdkerrors.Wrap(types.ErrInvalidConsensus(k.codespace), "cannot update client")     }      clientState, found := k.GetClientState(ctx, clientID)     if !found {         return sdkerrors.Wrap(types.ErrClientNotFound(k.codespace, clientID), "cannot update client")     }      if clientState.Frozen {         return sdkerrors.Wrap(types.ErrClientFrozen(k.codespace, clientID), "cannot update client")     }      consensusState, found := k.GetConsensusState(ctx, clientID)     if !found {         return sdkerrors.Wrap(types.ErrConsensusStateNotFound(k.codespace), "cannot update client")     }      if header.GetHeight() < consensusState.GetHeight() {         return sdkerrors.Wrap(             sdk.ErrInvalidSequence(                 fmt.Sprintf("header height < consensus height (%d < %d)", header.GetHeight(), consensusState.GetHeight()),             ),             "cannot update client",         )     }      consensusState, err := consensusState.CheckValidityAndUpdateState(header)     if err != nil {         return sdkerrors.Wrap(err, "cannot update client")     }      k.SetConsensusState(ctx, clientID, consensusState)     k.SetVerifiedRoot(ctx, clientID, consensusState.GetHeight(), consensusState.GetRoot())     k.Logger(ctx).Info(fmt.Sprintf("client %s updated to height %d", clientID, consensusState.GetHeight()))     return nil }

k.SetConsensusState(ctx, clientID, consensusState), k.SetVerifiedRoot(ctx, clientID, consensusState.GetHeight(), consensusState.GetRoot())与create client类似, 伪代码中也缺失, (看来是有意想要这么设置的), 其中核心函数应该是CheckValidityAndUpdateState()的方法, 上文有该函数的分析, 和我的个人看法.

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注