defparse_deposit_data(deposit_event_data)->bytes[]:"""
Parses deposit data from DepositContract.DepositEvent data
从 DepositContract.DepositEvent 数据解析存款数据
"""passdefis_valid_deposit_event_data(deposit_event_data:bytes)->bool:"""
Verifies the layout of the DepositEvent. Returns `False` if the layout is unsupported,
`True` if the layout is of the expected format.
验证 DepositEvent 的布局。如果不支持该布局,则返回 `False`,
如果该布局是预期的格式,则返回 `True`。
"""iflen(deposit_event_data)!=576:returnFalsepubkey_offset=int.from_bytes(deposit_event_data[0:32],byteorder='big',signed=False)withdrawal_credentials_offset=int.from_bytes(deposit_event_data[32:64],byteorder='big',signed=False)amount_offset=int.from_bytes(deposit_event_data[64:96],byteorder='big',signed=False)signature_offset=int.from_bytes(deposit_event_data[96:128],byteorder='big',signed=False)index_offset=int.from_bytes(deposit_event_data[128:160],byteorder='big',signed=False)if(pubkey_offset!=160orwithdrawal_credentials_offset!=256oramount_offset!=320orsignature_offset!=384orindex_offset!=512):returnFalse# These sizes are the sizes of the relevant data
# 这些大小是相关数据的大小
pubkey_size=int.from_bytes(deposit_event_data[pubkey_offset:pubkey_offset+32],byteorder='big',signed=False)withdrawal_credentials_size=int.from_bytes(deposit_event_data[withdrawal_credentials_offset:withdrawal_credentials_offset+32],byteorder='big',signed=False)amount_size=int.from_bytes(deposit_event_data[amount_offset:amount_offset+32],byteorder='big',signed=False)signature_size=int.from_bytes(deposit_event_data[signature_offset:signature_offset+32],byteorder='big',signed=False)index_size=int.from_bytes(deposit_event_data[index_offset:index_offset+32],byteorder='big',signed=False)return(pubkey_size==48andwithdrawal_credentials_size==32andamount_size==8andsignature_size==96andindex_size==8)defevent_data_to_deposit_request(deposit_event_data)->bytes:deposit_data=parse_deposit_data(deposit_event_data)pubkey=Bytes48(deposit_data[0])withdrawal_credentials=Bytes32(deposit_data[1])amount=deposit_data[2]# 8 bytes uint64 LE
signature=Bytes96(deposit_data[3])index=deposit_data[4]# 8 bytes uint64 LE
returnpubkey+withdrawal_credentials+amount+signature+indexdefget_deposit_request_data(receipts)# Retrieve all deposits made in the block
# 检索在区块中进行的所有存款
deposit_requests=[]forreceiptinreceipts:forloginreceipt.logs:iflog.address==DEPOSIT_CONTRACT_ADDRESS:iflen(log.topics)>0andlog.topics[0]==DEPOSIT_EVENT_SIGNATURE_HASH:assertis_valid_deposit_event_data(log.data),'invalid deposit log: unsupported data layout'deposit_request=event_data_to_deposit_request(log.data)deposit_requests.append(deposit_request)# Concatenate list of deposit request data
# 连接存款请求数据列表
returnb''.join(deposit_requests)
在最便宜的情况下(当所有存储槽都是热的时候,并且只需要修改单个叶子节点),存款合约中的代码运行需要 15,650 gas。批量存款中的某些存款成本更高,但是当分摊到大量存款时,这些成本很小,约为每个存款 ~1,000 gas。根据当前的 gas 定价规则,额外收取 6,900 gas 以进行传递 ETH 的 CALL,这是 gas 定价效率低下的一个案例,并且将来可能会降低。为了未来的健壮性,信标链需要能够在 30M gas 区块中承受 1,916 笔存款(每个存款 15,650 gas)。根据现行规则,30M gas 区块中的限制小于 1,271 笔存款。
执行层
以 1 ETH 作为最小存款金额,每字节存款数据的最低成本为 1 ETH/192 ~ 5,208,333 Gwei。这比事务的 calldata 的字节成本高几个数量级,因此将存款操作添加到区块不会增加执行层的 DoS 攻击面。
共识层
存款处理消耗最多的计算是签名验证。其复杂性受每个区块的最大存款数量的限制,目前在 30M gas 区块中约为 1,271 个。因此,大约是 ~1,271 个签名验证,大约需要 ~1.2 秒的处理时间(没有诸如批量签名验证之类的优化)。攻击者需要花费 1,000 ETH 才能将阻止处理速度降低一秒钟,从长远来看,这是一种不可持续且不可行的攻击。