该函数有详尽的函数解释, 大意为: 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()的方法, 上文有该函数的分析, 和我的个人看法.