零点课堂 | 利用雪崩算法主动协调交易本地状态(2)
创建信号
提供查询服务的节点,都必须维护一个secp256k1密钥对,该密钥用于授权
和验证下注消息的身份信息。下注动作是通过下注者使用公钥签署一个包含身份的信息加入连接消息。消息是通过ECDSA签署,使用组成币块的UTXO的公钥和私钥签署。(这一段看不懂,原文如下:Queryable nodes must all maintain an secp256k1 key pair whichis used by queriers to authenticate messages against a stake. Staking is doneby crafting and signing a Joinmessage containingthe Identity public key a list of outpoints controlled by the staker. Thismessage is signed using ECDSA by the Identity private key and by the public keythat controls each UTXO represented by the committed outpoint.)
现在只支持如下UTXO:
· P2PK(Pay-to-Pubkey)
· P2PKH
将来可能支持以下类型:
· 多重签名
· 精心定义的P2SH脚本。
验证
要验证一个连接消息的真伪,及其对应下注的客户端的身份,必须通过将消息的签名移除,并生成规范的序列化。然后验证程序要检查身份签名的正确性。接下来,要在提取公钥的同时,对照匹配输出点。最后,加载每个提交的UTXO,检查它们的类型,检查匹配的公钥是否正确,并确保币块足够大。(这段太复杂了,看不懂,原文是:To validate a Join message and its stake a client must firstgenerate the canonical serialized message by removing the signatures. Then itshould check that the Identity signature correctly signs the canonical message.Next it needs to verify each outpoint signature against its matching committedoutpoint, while simultaNEOusly extracting the public key. Finally it load eachof the committed UTXOs, check their type, check that the matching public key iscorrect, and ensure that Coin Blocks is sufficient.)
DAG格式
雪崩算法有效性的核心是DAG(有向无环图),它允许我们通过单个Snowball实例,来接受或拒绝整个链的状态。DAG图的连接性越强,完成所有状态最终确定所需要的Snowball实例就越少,不过,如果DAG图过于复杂,会导致体统效率都会浪费在构造图的边上。
解决方案是使用链中已经存在的所有自然形成的对象边,而不是人为再生成新的。我们通过定义给定顶点,来形成新的边,具体类型取决于如下:
一笔交易会从每一个父交易那里都形成一条边。
一个块,会从它的父块里形成一条边,以及从每一笔被该区块承诺的交易那里形成一条边。
冲突集
区块中每一笔存在于冲突集的交易,都要基于互斥排除点。这些要点如下:
· 一个交易的冲突集是所有使用相同UTXO花费的交易
· 一个区块的冲突集是所有相同高度的区块,包含了相同交易,或者包含了相冲突的交易
解决冲突集的过程是最终接受一个项的过程,同时意味着拒绝了所有其他项
循环采样
每一个客户端都应该持续为未完成的项进行循环采样,每次循环最多可以达到4096个请求。每次重复采样,客户端们应该随机选择要查询的节点,发送一个项目请求,并且通过投票累加器来返回投票结果。通过伪代码来描述如下:
while items= getItemsToSample():
peer = getRandomPeer()
votes = query(peer, items)
accumulateVotes(votes)
投票累加器
投票有三个选项值:no(0),yes(1),或者弃权(2)。通过将它们放入Snowball投票累加器来处理,该累加器保持最后K张选票,接受状态,以及雪崩白皮书里描述的对该状态的可信度。参数选择为k=8,