from__future__importannotationsfromtypingimportList,Optional,TuplefromdataclassesimportdataclassfromabcimportABC,abstractmethodfromeip_4881importDEPOSIT_CONTRACT_DEPTH,Hash32,sha256,to_le_bytes,zerohashes@dataclassclassDepositTreeSnapshot:finalized:List[Hash32,DEPOSIT_CONTRACT_DEPTH]deposit_root:Hash32deposit_count:uint64execution_block_hash:Hash32execution_block_height:uint64defcalculate_root(self)->Hash32:size=self.deposit_countindex=len(self.finalized)root=zerohashes[0]forlevelinrange(0,DEPOSIT_CONTRACT_DEPTH):if(size&1)==1:index-=1root=sha256(self.finalized[index]+root)else:root=sha256(root+zerohashes[level])size>>=1returnsha256(root+to_le_bytes(self.deposit_count))deffrom_tree_parts(finalized:List[Hash32],deposit_count:uint64,execution_block:Tuple[Hash32,uint64])->DepositTreeSnapshot:snapshot=DepositTreeSnapshot(finalized,zerohashes[0],deposit_count,execution_block[0],execution_block[1])# A real implementation should store the deposit_root from the eth1_data passed to
# DepositTree.finalize() instead of relying on calculate_root() here. This allows
# 真正的实现应该存储传递给 DepositTree.finalize() 的 eth1_data 中的 deposit_root,而不是依赖于此处的 calculate_root()。这允许
# the snapshot to be validated using calculate_root().
# 使用 calculate_root() 验证快照。
snapshot.deposit_root=snapshot.calculate_root()returnsnapshot@dataclassclassDepositTree:tree:MerkleTreemix_in_length:uintfinalized_execution_block:Optional[Tuple[Hash32,uint64]]defnew()->DepositTree:merkle=MerkleTree.create([],DEPOSIT_CONTRACT_DEPTH)returnDepositTree(merkle,0,None)defget_snapshot(self)->DepositTreeSnapshot:assert(self.finalized_execution_blockisnotNone)finalized=[]deposit_count=self.tree.get_finalized(finalized)returnDepositTreeSnapshot.from_tree_parts(finalized,deposit_count,self.finalized_execution_block)deffrom_snapshot(snapshot:DepositTreeSnapshot)->DepositTree:# decent validation check on the snapshot
# 对快照进行不错的验证检查
assert(snapshot.deposit_root==snapshot.calculate_root())finalized_execution_block=(snapshot.execution_block_hash,snapshot.execution_block_height)tree=MerkleTree.from_snapshot_parts(snapshot.finalized,snapshot.deposit_count,DEPOSIT_CONTRACT_DEPTH)returnDepositTree(tree,snapshot.deposit_count,finalized_execution_block)deffinalize(self,eth1_data:Eth1Data,execution_block_height:uint64):self.finalized_execution_block=(eth1_data.block_hash,execution_block_height)self.tree.finalize(eth1_data.deposit_count,DEPOSIT_CONTRACT_DEPTH)defget_proof(self,index:uint)->Tuple[Hash32,List[Hash32]]:assert(self.mix_in_length>0)# ensure index > finalized deposit index
# 确保索引 > 最终确定的存款索引
assert(index>self.tree.get_finalized([])-1)leaf,proof=self.tree.generate_proof(index,DEPOSIT_CONTRACT_DEPTH)proof.append(to_le_bytes(self.mix_in_length))returnleaf,proofdefget_root(self)->Hash32:returnsha256(self.tree.get_root()+to_le_bytes(self.mix_in_length))defpush_leaf(self,leaf:Hash32):self.mix_in_length+=1self.tree=self.tree.push_leaf(leaf,DEPOSIT_CONTRACT_DEPTH)classMerkleTree():@abstractmethoddefget_root(self)->Hash32:pass@abstractmethoddefis_full(self)->bool:pass@abstractmethoddefpush_leaf(self,leaf:Hash32,level:uint)->MerkleTree:pass@abstractmethoddeffinalize(self,deposits_to_finalize:uint,level:uint)->MerkleTree:pass@abstractmethoddefget_finalized(self,result:List[Hash32])->uint:# returns the number of finalized deposits in the tree
# 返回树中最终确定的存款数量
# while populating result with the finalized hashes
# 同时使用最终确定的哈希填充结果
passdefcreate(leaves:List[Hash32],depth:uint)->MerkleTree:ifnot(leaves):returnZero(depth)ifnot(depth):returnLeaf(leaves[0])split=min(2**(depth-1),len(leaves))left=MerkleTree.create(leaves[0:split],depth-1)right=MerkleTree.create(leaves[split:],depth-1)returnNode(left,right)deffrom_snapshot_parts(finalized:List[Hash32],deposits:uint,level:uint)->MerkleTree:ifnot(finalized)ornot(deposits):# empty tree
# 空树
returnZero(level)ifdeposits==2**level:returnFinalized(deposits,finalized[0])left_subtree=2**(level-1)ifdeposits<=left_subtree:left=MerkleTree.from_snapshot_parts(finalized,deposits,level-1)right=Zero(level-1)returnNode(left,right)else:left=Finalized(left_subtree,finalized[0])right=MerkleTree.from_snapshot_parts(finalized[1:],deposits-left_subtree,level-1)returnNode(left,right)defgenerate_proof(self,index:uint,depth:uint)->Tuple[Hash32,List[Hash32]]:proof=[]node=selfwhiledepth>0:ith_bit=(index>>(depth-1))&0x1ifith_bit==1:proof.append(node.left.get_root())node=node.rightelse:proof.append(node.right.get_root())node=node.leftdepth-=1proof.reverse()returnnode.get_root(),proof@dataclassclassFinalized(MerkleTree):deposit_count:uinthash:Hash32defget_root(self)->Hash32:returnself.hashdefis_full(self)->bool:returnTruedeffinalize(self,deposits_to_finalize:uint,level:uint)->MerkleTree:returnselfdefget_finalized(self,result:List[Hash32])->uint:result.append(self.hash)returnself.deposit_count@dataclassclassLeaf(MerkleTree):hash:Hash32defget_root(self)->Hash32:returnself.hashdefis_full(self)->bool:returnTruedeffinalize(self,deposits_to_finalize:uint,level:uint)->MerkleTree:returnFinalized(1,self.hash)defget_finalized(self,result:List[Hash32])->uint:return0@dataclassclassNode(MerkleTree):left:MerkleTreeright:MerkleTreedefget_root(self)->Hash32:returnsha256(self.left.get_root()+self.right.get_root())defis_full(self)->bool:returnself.right.is_full()defpush_leaf(self,leaf:Hash32,level:uint)->MerkleTree:ifnot(self.left.is_full()):self.left=self.left.push_leaf(leaf,level-1)else:self.right=self.right.push_leaf(leaf,level-1)returnselfdeffinalize(self,deposits_to_finalize:uint,level:uint)->MerkleTree:deposits=2**levelifdeposits<=deposits_to_finalize:returnFinalized(deposits,self.get_root())self.left=self.left.finalize(deposits_to_finalize,level-1)ifdeposits_to_finalize>deposits/2:remaining=deposits_to_finalize-deposits/2self.right=self.right.finalize(remaining,level-1)returnselfdefget_finalized(self,result:List[Hash32])->uint:returnself.left.get_finalized(result)+self.right.get_finalized(result)@dataclassclassZero(MerkleTree):n:uint64defget_root(self)->Hash32:ifself.n==DEPOSIT_CONTRACT_DEPTH:# Handle the entirely empty tree case. This is included for
# 处理完全空树的情况。 包含此项是为了
# consistency/clarity as the zerohashes array is typically
# 一致性/清晰起见,因为 zerohashes 数组通常
# only defined from 0 to DEPOSIT_CONTRACT_DEPTH - 1.
# 仅定义为从 0 到 DEPOSIT_CONTRACT_DEPTH - 1。
returnsha256(zerohashes[self.n-1]+zerohashes[self.n-1])returnzerohashes[self.n]defis_full(self)->bool:returnFalsedefpush_leaf(self,leaf:Hash32,level:uint)->MerkleTree:returnMerkleTree.create([leaf],level)defget_finalized(self,result:List[Hash32])->uint:return0