diff --git a/src/xtopcom/xevm_common/src/xeth_header.cpp b/src/xtopcom/xevm_common/src/xeth_header.cpp index df79a6556..5d89fc5b4 100644 --- a/src/xtopcom/xevm_common/src/xeth_header.cpp +++ b/src/xtopcom/xevm_common/src/xeth_header.cpp @@ -39,7 +39,8 @@ bool xeth_header_t::operator==(xeth_header_t const & rhs) const { (this->transactions_root == rhs.transactions_root) && (this->receipts_root == rhs.receipts_root) && (this->bloom == rhs.bloom) && (this->difficulty == rhs.difficulty) && (this->number == rhs.number) && (this->gas_limit == rhs.gas_limit) && (this->gas_used == rhs.gas_used) && (this->time == rhs.time) && (this->extra == rhs.extra) && (this->mix_digest == rhs.mix_digest) && (this->nonce == rhs.nonce) && (this->base_fee_per_gas == rhs.base_fee_per_gas) && - (this->withdrawals_root == rhs.withdrawals_root) && (this->blob_gas_used == rhs.blob_gas_used) && (this->excess_blob_gas == rhs.excess_blob_gas) && (this->parent_beacon_root == rhs.parent_beacon_root); + (this->withdrawals_root == rhs.withdrawals_root) && (this->blob_gas_used == rhs.blob_gas_used) && (this->excess_blob_gas == rhs.excess_blob_gas) && + (this->parent_beacon_root == rhs.parent_beacon_root) && (this->requests_hash == rhs.requests_hash); } xh256_t xeth_header_t::calc_hash(bool const partial) const { @@ -146,6 +147,11 @@ xbytes_t xeth_header_t::encode_rlp(bool const partial) const { out.insert(out.end(), tmp.begin(), tmp.end()); } + if (requests_hash.has_value()) { + auto tmp = RLP::encode(requests_hash.value().asArray()); + out.insert(out.end(), tmp.begin(), tmp.end()); + } + return RLP::encodeList(out); } @@ -264,6 +270,15 @@ void xeth_header_t::decode_rlp(xbytes_t const & bytes, std::error_code & ec) { parent_beacon_root = xh256_t{xspan_t{l.decoded[19]}}; } + if (l.decoded.size() >= 21) { + if (l.decoded[20].size() != xh256_t::size()) { + xwarn("xeth_header_t::decode_rlp failed, rlp requests hash invalid"); + ec = error::xerrc_t::rlp_bytes_invalid; + return; + } + requests_hash = xh256_t{xspan_t{l.decoded[20]}}; + } + { xbytes_t rlp_bytes = bytes; auto const & encoded_bytes = encode_rlp(); @@ -329,6 +344,10 @@ void xeth_header_t::print() const { if (parent_beacon_root.has_value()) { printf("parent_beacon_root: %s\n", parent_beacon_root.value().hex().c_str()); } + + if (requests_hash.has_value()) { + printf("requests_hash: %s\n", requests_hash.value().hex().c_str()); + } } xeth_header_info_t::xeth_header_info_t(bigint difficult_sum, xh256_t parent_hash, bigint number) diff --git a/src/xtopcom/xevm_common/xcrosschain/xeth2.h b/src/xtopcom/xevm_common/xcrosschain/xeth2.h index 0d638006d..635c07bfc 100644 --- a/src/xtopcom/xevm_common/xcrosschain/xeth2.h +++ b/src/xtopcom/xevm_common/xcrosschain/xeth2.h @@ -42,6 +42,14 @@ constexpr auto compute_sync_committee_period(xslot_t const slot) ->xperiod_t { return compute_epoch_at_slot(slot) / EPOCHS_PER_SYNC_COMMITTEE_PERIOD; } +constexpr static uint32_t floorlog2(uint32_t x) { + return x == 0 ? 0 : 31 - __builtin_clz(x); +} + +constexpr static uint32_t get_subtree_index(uint32_t generalized_index) { + return generalized_index % (1 << floorlog2(generalized_index)); +} + enum class xtop_network_id : uint8_t { mainnet, kiln, goerli, sepolia }; using xnetwork_id_t = xtop_network_id; @@ -70,6 +78,26 @@ struct xtop_proof_size { }; using xproof_size_t = xtop_proof_size; +struct xtop_generalized_index { + uint32_t finality_tree_depth{}; + uint32_t finality_tree_index{}; + uint32_t sync_committee_tree_depth{}; + uint32_t sync_committee_tree_index{}; + + xtop_generalized_index() = default; + xtop_generalized_index(uint32_t const finality_tree_depth, + uint32_t const finality_tree_index, + uint32_t const sync_committee_tree_depth, + uint32_t const sync_committee_tree_index) + : finality_tree_depth{finality_tree_depth} + , finality_tree_index{finality_tree_index} + , sync_committee_tree_depth{sync_committee_tree_depth} + , sync_committee_tree_index{sync_committee_tree_index} { + } +}; + +using xgeneralized_index_t = xtop_generalized_index; + struct xtop_fork_version { std::array fork_version{{0, 0, 0, 0}}; @@ -868,6 +896,9 @@ struct xtop_network_config { xfork_version_t deneb_fork_version; uint64_t deneb_fork_epoch{std::numeric_limits::max()}; + xfork_version_t electra_fork_version; + uint64_t electra_fork_epoch{std::numeric_limits::max()}; + explicit xtop_network_config(xnetwork_id_t const network_id) { switch (network_id) { case xnetwork_id_t::mainnet: { @@ -885,6 +916,9 @@ struct xtop_network_config { deneb_fork_version = xfork_version_t{0x04, 0x00, 0x00, 0x00}; deneb_fork_epoch = 269568; + electra_fork_version = xfork_version_t{0x05, 0x00, 0x00, 0x00}; + electra_fork_epoch = 364032; + break; } @@ -921,6 +955,9 @@ struct xtop_network_config { deneb_fork_version = xfork_version_t{0x90, 0x00, 0x00, 0x73}; deneb_fork_epoch = 132608; + electra_fork_version = xfork_version_t{0x90, 0x00, 0x00, 0x74}; + electra_fork_epoch = 222464; + break; } default: { @@ -931,6 +968,10 @@ struct xtop_network_config { } auto compute_fork_version(xepoch_t const epoch) const -> optional { + if (epoch >= this->electra_fork_epoch) { + return this->electra_fork_version; + } + if (epoch >= this->deneb_fork_epoch) { return this->deneb_fork_version; } @@ -975,6 +1016,31 @@ struct xtop_network_config { auto compute_proof_size_by_slot(xslot_t const slot) const -> xproof_size_t { return this->compute_proof_size(compute_epoch_at_slot(slot)); } + + auto get_generalized_index_constants(xslot_t const slot) const -> xgeneralized_index_t { + uint32_t FINALIZED_ROOT_INDEX(105); + uint32_t NEXT_SYNC_COMMITTEE_INDEX(55); + uint32_t FINALIZED_ROOT_INDEX_ELECTRA(169); + uint32_t NEXT_SYNC_COMMITTEE_INDEX_ELECTRA(87); + + xepoch_t epoch = compute_epoch_at_slot(slot); + + if (epoch >= this->electra_fork_epoch) { + return xgeneralized_index_t { + floorlog2(FINALIZED_ROOT_INDEX_ELECTRA), //finality_tree_depth + get_subtree_index(FINALIZED_ROOT_INDEX_ELECTRA), //finality_tree_index + floorlog2(NEXT_SYNC_COMMITTEE_INDEX_ELECTRA), //sync_committee_tree_depth + get_subtree_index(NEXT_SYNC_COMMITTEE_INDEX_ELECTRA), //sync_committee_tree_index + }; + } else { + return xgeneralized_index_t { + floorlog2(FINALIZED_ROOT_INDEX), //finality_tree_depth + get_subtree_index(FINALIZED_ROOT_INDEX), //finality_tree_index + floorlog2(NEXT_SYNC_COMMITTEE_INDEX), //sync_committee_tree_depth + get_subtree_index(NEXT_SYNC_COMMITTEE_INDEX), //sync_committee_tree_index + }; + } + } }; using xnetwork_config_t = xtop_network_config; diff --git a/src/xtopcom/xevm_common/xcrosschain/xeth_header.h b/src/xtopcom/xevm_common/xcrosschain/xeth_header.h index 3223dd5f8..2a6c27f70 100644 --- a/src/xtopcom/xevm_common/xcrosschain/xeth_header.h +++ b/src/xtopcom/xevm_common/xcrosschain/xeth_header.h @@ -42,6 +42,7 @@ struct xeth_header_t { optional blob_gas_used; optional excess_blob_gas; optional parent_beacon_root; + optional requests_hash; mutable xh256_t hash; mutable xh256_t partial_hash; diff --git a/src/xtopcom/xevm_contract_runtime/src/xevm_eth2_client_contract.cpp b/src/xtopcom/xevm_contract_runtime/src/xevm_eth2_client_contract.cpp index 76bb54852..3b29a8104 100644 --- a/src/xtopcom/xevm_contract_runtime/src/xevm_eth2_client_contract.cpp +++ b/src/xtopcom/xevm_contract_runtime/src/xevm_eth2_client_contract.cpp @@ -14,24 +14,8 @@ NS_BEG4(top, contract_runtime, evm, sys_contract) using namespace evm_common::eth2; -constexpr static uint32_t floorlog2(uint32_t x) { - return x == 0 ? 0 : 31 - __builtin_clz(x); -} - -constexpr static uint32_t get_subtree_index(uint32_t generalized_index) { - return generalized_index % (1 << floorlog2(generalized_index)); -} - - constexpr static uint64_t MIN_SYNC_COMMITTEE_PARTICIPANTS{1}; -constexpr static uint32_t FINALIZED_ROOT_INDEX{105}; -constexpr static uint32_t NEXT_SYNC_COMMITTEE_INDEX{55}; -constexpr static uint32_t FINALITY_TREE_DEPTH{floorlog2(FINALIZED_ROOT_INDEX)}; -constexpr static uint32_t FINALITY_TREE_INDEX{get_subtree_index(FINALIZED_ROOT_INDEX)}; -constexpr static uint32_t SYNC_COMMITTEE_TREE_DEPTH{floorlog2(NEXT_SYNC_COMMITTEE_INDEX)}; -constexpr static uint32_t SYNC_COMMITTEE_TREE_INDEX{get_subtree_index(NEXT_SYNC_COMMITTEE_INDEX)}; - constexpr uint64_t hashes_gc_threshold = 51000; //static std::string covert_committee_bits_to_bin_str(xbytes_t const & bits) { @@ -850,11 +834,13 @@ bool xtop_evm_eth2_client_contract::verify_finality_branch(state_ptr const & sta branch_data.insert(branch_data.end(), b.begin(), b.end()); } xh256_t merkle_root; + xnetwork_config_t const config{m_network}; + xgeneralized_index_t generalized_index = config.get_generalized_index_constants(update.finality_update.header_update.beacon_header.slot); if (false == unsafe_merkle_proof(update.finality_update.header_update.beacon_header.tree_hash_root().data(), branch_data.data(), branch_data.size(), - FINALITY_TREE_DEPTH, - FINALITY_TREE_INDEX, + generalized_index.finality_tree_depth, + generalized_index.finality_tree_index, merkle_root.data())) { xwarn("xtop_evm_eth2_client_contract::verify_finality_branch header unsafe_merkle_proof error"); return false; @@ -865,8 +851,7 @@ bool xtop_evm_eth2_client_contract::verify_finality_branch(state_ptr const & sta to_hex(update.attested_beacon_header.state_root).c_str()); return false; } - - xnetwork_config_t const config{m_network}; + if (false == validate_beacon_block_header_update(config, update.finality_update.header_update)) { xwarn("xtop_evm_eth2_client_contract::verify_finality_branch validate_beacon_block_header_update error"); return false; @@ -883,8 +868,8 @@ bool xtop_evm_eth2_client_contract::verify_finality_branch(state_ptr const & sta if (false == unsafe_merkle_proof(update.sync_committee_update.next_sync_committee.tree_hash_root().data(), branch_data.data(), branch_data.size(), - SYNC_COMMITTEE_TREE_DEPTH, - SYNC_COMMITTEE_TREE_INDEX, + generalized_index.sync_committee_tree_depth, + generalized_index.sync_committee_tree_index, merkle_root.data())) { xwarn("xtop_evm_eth2_client_contract::verify_finality_branch committee unsafe_merkle_proof error"); return false; diff --git a/src/xtopcom/xevm_engine_rs/engine-eth2-utility/src/consensus.rs b/src/xtopcom/xevm_engine_rs/engine-eth2-utility/src/consensus.rs index 6d11ed842..37cf91f18 100644 --- a/src/xtopcom/xevm_engine_rs/engine-eth2-utility/src/consensus.rs +++ b/src/xtopcom/xevm_engine_rs/engine-eth2-utility/src/consensus.rs @@ -56,6 +56,8 @@ pub struct NetworkConfig { pub capella_fork_epoch: u64, pub deneb_fork_version: ForkVersion, pub deneb_fork_epoch: u64, + pub electra_fork_version: ForkVersion, + pub electra_fork_epoch: u64, } impl NetworkConfig { @@ -73,6 +75,8 @@ impl NetworkConfig { capella_fork_epoch: 194048, deneb_fork_version: [0x04, 0x00, 0x00, 0x00], deneb_fork_epoch: 269568, + electra_fork_version: [0x05, 0x00, 0x00, 0x00], + electra_fork_epoch: 364032, }, Network::Goerli => Self { genesis_validators_root: [ @@ -86,6 +90,8 @@ impl NetworkConfig { capella_fork_epoch: 162304, deneb_fork_version: [0x04, 0x00, 0x10, 0x20], deneb_fork_epoch: 231680, + electra_fork_version: [0x00, 0x00, 0x00, 0x00], // Not supported + electra_fork_epoch: u64::MAX, // Not supported }, Network::Kiln => Self { genesis_validators_root: [ @@ -99,6 +105,8 @@ impl NetworkConfig { capella_fork_epoch: 150, deneb_fork_version: [0x90, 0x00, 0x00, 0x73], deneb_fork_epoch: 132608, + electra_fork_version: [0x00, 0x00, 0x00, 0x00], // Not supported + electra_fork_epoch: u64::MAX, // Not supported }, Network::Sepolia => Self { genesis_validators_root: [ @@ -110,11 +118,17 @@ impl NetworkConfig { capella_fork_epoch: 56832, deneb_fork_version: [0x90, 0x00, 0x00, 0x73], deneb_fork_epoch: 132608, + electra_fork_version: [0x90, 0x00, 0x00, 0x74], + electra_fork_epoch: 222464, }, } } pub fn compute_fork_version(&self, epoch: Epoch) -> Option { + if epoch >= self.electra_fork_epoch { + return Some(self.electra_fork_version); + } + if epoch >= self.deneb_fork_epoch { return Some(self.deneb_fork_version); }