mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 00:31:02 +00:00
Snowbridge: Synchronize from Snowfork repository (#3761)
This PR includes the following 2 improvements: ## Ethereum Client Author: @yrong ### Original Upstream PRs - https://github.com/Snowfork/polkadot-sdk/pull/123 - https://github.com/Snowfork/polkadot-sdk/pull/125 ### Description The Ethereum client syncs beacon headers as they are finalized, and imports every execution header. When a message is received, it is verified against the import execution header. This is unnecessary, since the execution header can be sent with the message as proof. The recent Deneb Ethereum upgrade made it easier to locate the relevant beacon header from an execution header, and so this improvement was made possible. This resolves a concern @svyatonik had in our initial Rococo PR: https://github.com/paritytech/polkadot-sdk/pull/2522#discussion_r1431270691 ## Inbound Queue Author: @yrong ### Original Upstream PR - https://github.com/Snowfork/polkadot-sdk/pull/118 ### Description When the AH sovereign account (who pays relayer rewards) is depleted, the inbound message will not fail. The relayer just will not receive rewards. Both these changes were done by @yrong, many thanks. ❤️ --------- Co-authored-by: claravanstaden <Cats 4 life!> Co-authored-by: Ron <yrong1997@gmail.com> Co-authored-by: Vincent Geddes <vincent@snowfork.com> Co-authored-by: Svyatoslav Nikolsky <svyatonik@gmail.com>
This commit is contained in:
@@ -6,9 +6,10 @@
|
||||
|
||||
use hex_literal::hex;
|
||||
use snowbridge_beacon_primitives::{
|
||||
types::deneb, updates::AncestryProof, BeaconHeader, ExecutionHeaderUpdate,
|
||||
NextSyncCommitteeUpdate, SyncAggregate, SyncCommittee, VersionedExecutionPayloadHeader,
|
||||
types::deneb, AncestryProof, BeaconHeader, ExecutionProof, NextSyncCommitteeUpdate,
|
||||
SyncAggregate, SyncCommittee, VersionedExecutionPayloadHeader,
|
||||
};
|
||||
use snowbridge_core::inbound::{InboundQueueFixture, Log, Message, Proof};
|
||||
use sp_core::U256;
|
||||
use sp_std::{boxed::Box, vec};
|
||||
|
||||
@@ -20,11 +21,11 @@ type Update = snowbridge_beacon_primitives::Update<SC_SIZE, SC_BITS_SIZE>;
|
||||
pub fn make_checkpoint() -> Box<CheckpointUpdate> {
|
||||
Box::new(CheckpointUpdate {
|
||||
header: BeaconHeader {
|
||||
slot: 2496,
|
||||
proposer_index: 2,
|
||||
parent_root: hex!("c99e49787106733eeebab4d93eb326e1f2214575c9d928f0c4ab0da0776f1622").into(),
|
||||
state_root: hex!("fbf8a08c86ef36bd173e37e733da4a78aa8e85fee99a990e858dd12a59087fde").into(),
|
||||
body_root: hex!("a2a8ad06901447b2807a9059580a4c40d8a941f325b1343c69f7c7c6c90e4ab0").into(),
|
||||
slot: 864,
|
||||
proposer_index: 4,
|
||||
parent_root: hex!("614e7672f991ac268cd841055973f55e1e42228831a211adef207bb7329be614").into(),
|
||||
state_root: hex!("5fa8dfca3d760e4242ab46d529144627aa85348a19173b6e081172c701197a4a").into(),
|
||||
body_root: hex!("0f34c083b1803666bb1ac5e73fa71582731a2cf37d279ff0a3b0cad5a2ff371e").into(),
|
||||
},
|
||||
current_sync_committee: SyncCommittee {
|
||||
pubkeys: [
|
||||
@@ -544,20 +545,20 @@ pub fn make_checkpoint() -> Box<CheckpointUpdate> {
|
||||
aggregate_pubkey: hex!("8fbd66eeec2ff69ef0b836f04b1d67d88bcd4dfd495061964ad757c77abe822a39fa1cd8ed0d4d9bc9276cea73fd745c").into(),
|
||||
},
|
||||
current_sync_committee_branch: vec![
|
||||
hex!("3ade38d498a062b50880a9409e1ca3a7fd4315d91eeb3bb83e56ac6bfe8d6a59").into(),
|
||||
hex!("93880225bf99a0c5ec22b266ff829837754e9c5edf37a68c05b8f803fd82fa45").into(),
|
||||
hex!("4c60656ec9a95fcf11030ad309c716b5b15beb7f60a0bcfc7c9d4eff505472ff").into(),
|
||||
hex!("22d1645fceb4bf9a695043dda19a53e784ec70df6a6b1bd66ea30eba1cca5f2f").into(),
|
||||
hex!("a8fc6cad84ceefc633ec56c2d031d525e1cb4b51c70eb252919fce5bba9a1fde").into(),
|
||||
hex!("3ade38d498a062b50880a9409e1ca3a7fd4315d91eeb3bb83e56ac6bfe8d6a59").into(),
|
||||
hex!("a9e90f89e7f90fd5d79a6bbcaf40ba5cfc05ab1b561ac51c84867c32248d5b1e").into(),
|
||||
hex!("bd1a76b03e02402bb24a627de1980a80ab17691980271f597b844b89b497ef75").into(),
|
||||
hex!("07bbcd27c7cad089023db046eda17e8209842b7d97add8b873519e84fe6480e7").into(),
|
||||
hex!("94c11eeee4cb6192bf40810f23486d8c75dfbc2b6f28d988d6f74435ede243b0").into(),
|
||||
],
|
||||
validators_root: hex!("270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69").into(),
|
||||
block_roots_root: hex!("d160b7687041891b73e54b06fc4e04f82d0fa8fdd76705895e216c6b24709dfe").into(),
|
||||
block_roots_root: hex!("b9aab9c388c4e4fcd899b71f62c498fc73406e38e8eb14aa440e9affa06f2a10").into(),
|
||||
block_roots_branch: vec![
|
||||
hex!("105290e42d98ab6a0ada6e55453cede36c672abf645eeb986b88d7487616e135").into(),
|
||||
hex!("9da41f274bcdf6122335443d9ce94d07163b48dba3e2f9499ff56f4e48b48b99").into(),
|
||||
hex!("ecea7e1d3152d8130e83afdfe34b4de4ba2b69a33c9471991096daf454de9cf5").into(),
|
||||
hex!("b2bf1758e50b2bfff29169fbc70fdb884b2b05bb615dbc53567574da6f4f1ae2").into(),
|
||||
hex!("cd87069daf70975779126d6af833b7d636c75ca4d5e750ebcad0e76408a5e5bf").into(),
|
||||
hex!("733422bd810895dab74cbbe07c69dd440cbb51f573181ad4dddac30fcdd0f41f").into(),
|
||||
hex!("9b9eca73ab01d14549c325ba1b4610bb20bf1f8ec2dbd649f9d8cc7f3cea75fa").into(),
|
||||
hex!("bcc666ad0ad9f9725cbd682bc95589d35b1b53b2a615f1e6e8dd5e086336becf").into(),
|
||||
hex!("3069b547a08f703a1715016e926cbd64e71f93f64fb68d98d8c8f1ab745c46e5").into(),
|
||||
hex!("c2de7e1097239404e17b263cfa0473533cc41e903cb03440d633bc5c27314cb4").into(),
|
||||
],
|
||||
})
|
||||
}
|
||||
@@ -567,13 +568,13 @@ pub fn make_sync_committee_update() -> Box<Update> {
|
||||
attested_header: BeaconHeader {
|
||||
slot: 129,
|
||||
proposer_index: 5,
|
||||
parent_root: hex!("e32b6c18f029e755b0273dc1c4fa2bc4979794c8286ad40276c1b8a8e36049d8").into(),
|
||||
state_root: hex!("5ec9dacf25a5f09f20be0c59246b3d8dcfe64bd085b4bac5cec180690339801e").into(),
|
||||
body_root: hex!("4080cf2412d6ff77fc3164ad6155423a7112f207f173145ec16371a93f481f87").into(),
|
||||
parent_root: hex!("c2def03fe44a2802130ca1a6d8406e4ccf4f344fec7075d4d84431cd4a8b0904").into(),
|
||||
state_root: hex!("fa62cde6666add7353d7aedcb61ebe3c6c84b5361e34f814825b1250affb5be4").into(),
|
||||
body_root: hex!("0f9c69f243fe7b5fa5860396c66c720a9e8b1e526e7914188930497cc4a9134c").into(),
|
||||
},
|
||||
sync_aggregate: SyncAggregate{
|
||||
sync_committee_bits: hex!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
sync_committee_signature: hex!("a761c3333fbb3d36bc8f65454f898da38001499dcd37494cf3d86940a995399ae649216ba4c985af154f83f72c8b1856079b7636a7a8d7d3f7602df2cbf699edb72b65253e82de4d9cc4db7377eafb22f799129f63f094a21c00675bdd5cc243").into(),
|
||||
sync_committee_signature: hex!("810cfde2afea3e276256c09bdf1cd321c33dcadeefddcfd24f488e6f756d917cfda90b5b437b3a4b4ef880985afa28a40cf565ec0a82877ddee36adc01d55d9d4a911ae3e22556e4c2636f1c707366fba019fb49450440fcd263d0b054b04bf0").into(),
|
||||
},
|
||||
signature_slot: 130,
|
||||
next_sync_committee_update: Some(NextSyncCommitteeUpdate {
|
||||
@@ -1096,34 +1097,34 @@ pub fn make_sync_committee_update() -> Box<Update> {
|
||||
},
|
||||
next_sync_committee_branch: vec![
|
||||
hex!("3ade38d498a062b50880a9409e1ca3a7fd4315d91eeb3bb83e56ac6bfe8d6a59").into(),
|
||||
hex!("fd1e5ff5d4a15081efe3ff17857b1f95984c9a271b1c41c2f81f43e60c2cc541").into(),
|
||||
hex!("e1c97f93bb7352d395d1ff8ee29881572cb7eb5d71634783701171dcd30cd93d").into(),
|
||||
hex!("77fa2170ddbd89b15dae02f2e6cf9f76c8e00d1c4217320acffbe01576d0da61").into(),
|
||||
hex!("e97288e0627219087a024078d69445f34f0583a6350a7c3c40c39fd1fa6f8d68").into(),
|
||||
hex!("43276bee17fc9fba3f4866e902f0e5b5b308d79db91154bb8bf819973837a7d9").into(),
|
||||
hex!("5572348e13ce59446ca0ea7cfeed07579da05f121920a76559e19bda94dd81cd").into(),
|
||||
hex!("2d58adca9f3c742530de037f1933d6de1920ea4b68581613d4bc32b71547f221").into(),
|
||||
hex!("7072b3c6577cd5a89b3234968f316f54630bb97eafbdb59e5b61637a9640255f").into(),
|
||||
],
|
||||
}),
|
||||
finalized_header: BeaconHeader{
|
||||
slot: 64,
|
||||
proposer_index: 4,
|
||||
parent_root: hex!("0f7bc2353778c14c7f6dba0fc5fe6eec87228b0d3a5447b61dce67b4d9338de3").into(),
|
||||
state_root: hex!("feb990de653ce494c0a263f820eaf05a9300dbdc30cb6065ede602827bfccde4").into(),
|
||||
body_root: hex!("f5235cd8c24f2695fc5b7989926305c10ad8cf5a87d62a739f675f5543df2ec1").into(),
|
||||
parent_root: hex!("a876486aaad7ddb897f369fd22d0a9903cd61d00c9e0dfe7998dd68d1008c678").into(),
|
||||
state_root: hex!("818e21c3388575f8ccc9ff17ec79d5a57915bcd31bccf47770f65a18e068416b").into(),
|
||||
body_root: hex!("1d1f73b864b3bb7e11ff91b56ca1381e0f9ca8122b2c542db88243604c763019").into(),
|
||||
},
|
||||
finality_branch: vec![
|
||||
hex!("0200000000000000000000000000000000000000000000000000000000000000").into(),
|
||||
hex!("10c726fac935bf9657cc7476d3cfa7bedec5983dcfb59e8a7df6d0a619e108d7").into(),
|
||||
hex!("98e9116c6bb7f20de18800dc63e73e689d06d6a47d35b5e2b32cf093d475840d").into(),
|
||||
hex!("e1c97f93bb7352d395d1ff8ee29881572cb7eb5d71634783701171dcd30cd93d").into(),
|
||||
hex!("77fa2170ddbd89b15dae02f2e6cf9f76c8e00d1c4217320acffbe01576d0da61").into(),
|
||||
hex!("e97288e0627219087a024078d69445f34f0583a6350a7c3c40c39fd1fa6f8d68").into(),
|
||||
hex!("5572348e13ce59446ca0ea7cfeed07579da05f121920a76559e19bda94dd81cd").into(),
|
||||
hex!("2d58adca9f3c742530de037f1933d6de1920ea4b68581613d4bc32b71547f221").into(),
|
||||
hex!("7072b3c6577cd5a89b3234968f316f54630bb97eafbdb59e5b61637a9640255f").into(),
|
||||
],
|
||||
block_roots_root: hex!("6fcdfd1c3fb1bdd421fe59dddfff3855b5ed5e30373887991a0059d019ad12bc").into(),
|
||||
block_roots_root: hex!("715b08694bef183a6d94b3113d16a7129f89fc3edec85a7e0eaf6ef9153552ef").into(),
|
||||
block_roots_branch: vec![
|
||||
hex!("94b59531f172bc24f914bc0c10104ccb158676850f8cc3b47b6ddb7f096ebdd7").into(),
|
||||
hex!("22470ed9155a938587d44d5fa19217c0f939d8862e504e67cd8cb4d1b960795e").into(),
|
||||
hex!("feec3ef1a68f93849e71e84f90b99602cccc31868137b6887ca8244a4b979e8e").into(),
|
||||
hex!("4028c72c71b6ce80ea7d18b2c9471f4e4fa39746261a9921e832a4a2f9bdf7bb").into(),
|
||||
hex!("75f98062661785d3290b7bd998b64446582baa49210733fd4603e1a97cd45a44").into(),
|
||||
hex!("6fb757f44052f30c464810f01b0132adfa1a5446d8715b41e9af88eee1ee3e65").into(),
|
||||
hex!("5340ad5877c72dca689ca04bc8fedb78d67a4801d99887937edd8ccd29f87e82").into(),
|
||||
hex!("f5ff4b0c6190005015889879568f5f0d9c40134c7ec4ffdda47950dcd92395ad").into(),
|
||||
hex!("f2b3cb56753939a728ccad399a434ca490f018f2f331529ec0d8b2d59c509271").into(),
|
||||
],
|
||||
})
|
||||
}
|
||||
@@ -1131,95 +1132,180 @@ pub fn make_sync_committee_update() -> Box<Update> {
|
||||
pub fn make_finalized_header_update() -> Box<Update> {
|
||||
Box::new(Update {
|
||||
attested_header: BeaconHeader {
|
||||
slot: 2566,
|
||||
proposer_index: 6,
|
||||
parent_root: hex!("6eb9f13a2c496318ce1ab3087bbd872f5c9519a1a7ca8231a2453e3cb523af00").into(),
|
||||
state_root: hex!("c8cb12766113dff7e46d2917267bf33d0626d99dd47715fcdbc5c65fad3c04b4").into(),
|
||||
body_root: hex!("d8cfd0d7bc9bc3724417a1655bb0a67c0765ca36197320f4d834150b52ef1420").into(),
|
||||
slot: 933,
|
||||
proposer_index: 1,
|
||||
parent_root: hex!("f5fc63e2780ca302b97aea73fc95d74d702b5afe9a772c2b68f695026337b620").into(),
|
||||
state_root: hex!("d856d11636bc4d866e78be9e747b222b0977556a367ab42e4085277301438050").into(),
|
||||
body_root: hex!("5689091ab4eb76c2e876271add4924e1c66ce987c300c24aac2ad8c703e9a33f").into(),
|
||||
},
|
||||
sync_aggregate: SyncAggregate{
|
||||
sync_committee_bits: hex!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
sync_committee_signature: hex!("9296f9a0387f2cac47008e22ad7c3cd3d49d35384c13e6aa1eacca7dca7c3d2ca81515e50eb3396b9550ed20ef7d8fa2049a186598feb2c00e93728045fcff917733d1827481b8fc95f3913e27fc70112c2490496eb57bb7181f02c3f9fd471f").into(),
|
||||
sync_committee_signature: hex!("93a3d482fe2a2f7fd2b634169752a8fddf1dc28b23a020b398be8526faf37a74ca0f6db1bed78a9c7256c09a6115235e108e0e8a7ce09287317b0856c4b77dfa5adba6cf4c3ebea5bfa4cd2fcde80fd0a532f2defe65d530201d5d2258796559").into(),
|
||||
},
|
||||
signature_slot: 2567,
|
||||
signature_slot: 934,
|
||||
next_sync_committee_update: None,
|
||||
finalized_header: BeaconHeader {
|
||||
slot: 2496,
|
||||
proposer_index: 2,
|
||||
parent_root: hex!("c99e49787106733eeebab4d93eb326e1f2214575c9d928f0c4ab0da0776f1622").into(),
|
||||
state_root: hex!("fbf8a08c86ef36bd173e37e733da4a78aa8e85fee99a990e858dd12a59087fde").into(),
|
||||
body_root: hex!("a2a8ad06901447b2807a9059580a4c40d8a941f325b1343c69f7c7c6c90e4ab0").into(),
|
||||
slot: 864,
|
||||
proposer_index: 4,
|
||||
parent_root: hex!("614e7672f991ac268cd841055973f55e1e42228831a211adef207bb7329be614").into(),
|
||||
state_root: hex!("5fa8dfca3d760e4242ab46d529144627aa85348a19173b6e081172c701197a4a").into(),
|
||||
body_root: hex!("0f34c083b1803666bb1ac5e73fa71582731a2cf37d279ff0a3b0cad5a2ff371e").into(),
|
||||
},
|
||||
finality_branch: vec![
|
||||
hex!("4e00000000000000000000000000000000000000000000000000000000000000").into(),
|
||||
hex!("1b00000000000000000000000000000000000000000000000000000000000000").into(),
|
||||
hex!("10c726fac935bf9657cc7476d3cfa7bedec5983dcfb59e8a7df6d0a619e108d7").into(),
|
||||
hex!("98e9116c6bb7f20de18800dc63e73e689d06d6a47d35b5e2b32cf093d475840d").into(),
|
||||
hex!("958b8e43347f6df6fa5eb3d62d06a862381a6585aa40640dd1c0de11f1cf89c1").into(),
|
||||
hex!("f107dce04faa86a28fc5d4a618be9cb8d4fc3c23d6c42c3624f3ff4bf6586a03").into(),
|
||||
hex!("a501cdc02e86969ac3e4d0c5a36f4f049efaa1ab8cb6693f51d130eb52a80f30").into(),
|
||||
hex!("f12d9aededc72724e417b518fe6f847684f26f81616243dedf8c551cc7d504f5").into(),
|
||||
hex!("89a85d0907ab3fd6e00ae385f61d456c6191646404ae7b8d23d0e60440cf4d00").into(),
|
||||
hex!("9fc943b6020eb61d780d78bcc6f6102a81d2c868d58f36e61c6e286a2dc4d8c2").into(),
|
||||
],
|
||||
block_roots_root: hex!("d160b7687041891b73e54b06fc4e04f82d0fa8fdd76705895e216c6b24709dfe").into(),
|
||||
block_roots_root: hex!("b9aab9c388c4e4fcd899b71f62c498fc73406e38e8eb14aa440e9affa06f2a10").into(),
|
||||
block_roots_branch: vec![
|
||||
hex!("105290e42d98ab6a0ada6e55453cede36c672abf645eeb986b88d7487616e135").into(),
|
||||
hex!("9da41f274bcdf6122335443d9ce94d07163b48dba3e2f9499ff56f4e48b48b99").into(),
|
||||
hex!("ecea7e1d3152d8130e83afdfe34b4de4ba2b69a33c9471991096daf454de9cf5").into(),
|
||||
hex!("b2bf1758e50b2bfff29169fbc70fdb884b2b05bb615dbc53567574da6f4f1ae2").into(),
|
||||
hex!("cd87069daf70975779126d6af833b7d636c75ca4d5e750ebcad0e76408a5e5bf").into(),
|
||||
hex!("733422bd810895dab74cbbe07c69dd440cbb51f573181ad4dddac30fcdd0f41f").into(),
|
||||
hex!("9b9eca73ab01d14549c325ba1b4610bb20bf1f8ec2dbd649f9d8cc7f3cea75fa").into(),
|
||||
hex!("bcc666ad0ad9f9725cbd682bc95589d35b1b53b2a615f1e6e8dd5e086336becf").into(),
|
||||
hex!("3069b547a08f703a1715016e926cbd64e71f93f64fb68d98d8c8f1ab745c46e5").into(),
|
||||
hex!("c2de7e1097239404e17b263cfa0473533cc41e903cb03440d633bc5c27314cb4").into(),
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
pub fn make_execution_header_update() -> Box<ExecutionHeaderUpdate> {
|
||||
Box::new(ExecutionHeaderUpdate {
|
||||
pub fn make_execution_proof() -> Box<ExecutionProof> {
|
||||
Box::new(ExecutionProof {
|
||||
header: BeaconHeader {
|
||||
slot: 215,
|
||||
proposer_index: 2,
|
||||
parent_root: hex!("97518f531a252bb6ca547b21aca9da767943ec99211d3b15c804e34c3a523f45").into(),
|
||||
state_root: hex!("b088b5a3a8c90d6dc919a695cd7bb0267c6f983ea2e675c559ceb8f46cb90b67").into(),
|
||||
body_root: hex!("0ba23c8224fdd01531d5ad51486353bd524a0b4c20bca704e26d3210616f829b").into(),
|
||||
slot: 393,
|
||||
proposer_index: 4,
|
||||
parent_root: hex!("6545b47a614a1dd4cad042a0cdbbf5be347e8ffcdc02c6c64540d5153acebeef").into(),
|
||||
state_root: hex!("b62ac34a8cb82497be9542fe2114410c9f6021855b766015406101a1f3d86434").into(),
|
||||
body_root: hex!("04005fe231e11a5b7b1580cb73b177ae8b338bedd745497e6bb7122126a806db").into(),
|
||||
},
|
||||
ancestry_proof: Some(AncestryProof {
|
||||
header_branch: vec![
|
||||
hex!("97518f531a252bb6ca547b21aca9da767943ec99211d3b15c804e34c3a523f45").into(),
|
||||
hex!("5ce0db996bd499c2b4f7a93263d5aafd052f420efb617cce6fdd54e25516aa45").into(),
|
||||
hex!("84f0e373b66011ce774c7061440c0a50a51cce2b4b335395eee3e563d605597f").into(),
|
||||
hex!("48f9ccc5f9594142c18c3b5c39a99f0549329c6ab3ba06c9a50030eadca87770").into(),
|
||||
hex!("f89d6e311e05bc75a6f63ce118bccce254551f1a88d54c3b4f773f81f946bd99").into(),
|
||||
hex!("2edd6d893c22636675147c07dfcdb541a146e87c3f15b51c388be4868246dc9b").into(),
|
||||
hex!("d76b7de5f856e3208a91a42c9c398a7f4fab35e667bf916346050ae742514a2d").into(),
|
||||
hex!("83a2e233e76385953ca41de4c3afe60471a61f0cc1b3846b4a0670e3e563b747").into(),
|
||||
hex!("e783a5a109c2ad74e4eb53e8f6b11b31266a92a9e16c1fd5873109c5d41b282c").into(),
|
||||
hex!("d4ea1ef3869ee6a0fd0b19d7d70027d144eecd4f1d32cbf47632a0a9069164b9").into(),
|
||||
hex!("f8179564b58eb93a850d35e4156a04db651106442ad891c3e85155c1762792f1").into(),
|
||||
hex!("4cbb1edb48cf1e32fb30db60aaaeaf6190ffe4d0c8dbc96cec307daecb78be12").into(),
|
||||
hex!("6545b47a614a1dd4cad042a0cdbbf5be347e8ffcdc02c6c64540d5153acebeef").into(),
|
||||
hex!("fa84cc88ca53a72181599ff4eb07d8b444bce023fe2347c3b4f51004c43439d3").into(),
|
||||
hex!("cadc8ae211c6f2221c9138e829249adf902419c78eb4727a150baa4d9a02cc9d").into(),
|
||||
hex!("33a89962df08a35c52bd7e1d887cd71fa7803e68787d05c714036f6edf75947c").into(),
|
||||
hex!("2c9760fce5c2829ef3f25595a703c21eb22d0186ce223295556ed5da663a82cf").into(),
|
||||
hex!("e1aa87654db79c8a0ecd6c89726bb662fcb1684badaef5cd5256f479e3c622e1").into(),
|
||||
hex!("aa70d5f314e4a1fbb9c362f3db79b21bf68b328887248651fbd29fc501d0ca97").into(),
|
||||
hex!("160b6c235b3a1ed4ef5f80b03ee1c76f7bf3f591c92fca9d8663e9221b9f9f0f").into(),
|
||||
hex!("f68d7dcd6a07a18e9de7b5d2aa1980eb962e11d7dcb584c96e81a7635c8d2535").into(),
|
||||
hex!("1d5f912dfd6697110dd1ecb5cb8e77952eef57d85deb373572572df62bb157fc").into(),
|
||||
hex!("ffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b").into(),
|
||||
hex!("6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220").into(),
|
||||
hex!("b7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f").into(),
|
||||
],
|
||||
finalized_block_root: hex!("890a7f23b9ed2160901654be9efc575d6830ca860e2a97866ae3423fb7bd7231").into(),
|
||||
finalized_block_root: hex!("751414cd97c0624f922b3e80285e9f776b08fa22fd5f87391f2ed7ef571a8d46").into(),
|
||||
}),
|
||||
execution_header: VersionedExecutionPayloadHeader::Deneb(deneb::ExecutionPayloadHeader {
|
||||
parent_hash: hex!("d82ec63f5c5e6ba61d62f09c188f158e6449b94bdcc31941e68639eec3c4cf7a").into(),
|
||||
parent_hash: hex!("8092290aa21b7751576440f77edd02a94058429ce50e63a92d620951fb25eda2").into(),
|
||||
fee_recipient: hex!("0000000000000000000000000000000000000000").into(),
|
||||
state_root: hex!("8b65545fe5f3216b47b6339b9c91ca2b7f1032a970b04246d9e9fb4460ee34c3").into(),
|
||||
receipts_root: hex!("7b1f61b9714c080ef0be014e01657a15f45f0304b477beebc7ca5596c8033095").into(),
|
||||
logs_bloom: hex!("00000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000080000000000000000000000000000004000000000080000000000000000000000000000000000010100000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000040004000000000000002000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000200000000000010").into(),
|
||||
prev_randao: hex!("6d9e2a012d82b1b6cb0a2c1c1ed24cc16dbb56e6e39ae545371e0666ab057862").into(),
|
||||
block_number: 215,
|
||||
gas_limit: 64842908,
|
||||
gas_used: 119301,
|
||||
timestamp: 1705859527,
|
||||
extra_data: hex!("d983010d0a846765746888676f312e32312e358664617277696e").into(),
|
||||
state_root: hex!("96a83e9ddf745346fafcb0b03d57314623df669ed543c110662b21302a0fae8b").into(),
|
||||
receipts_root: hex!("dccdfceea05036f7b61dcdabadc937945d31e68a8d3dfd4dc85684457988c284").into(),
|
||||
logs_bloom: hex!("00000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000080000000400000000000000000000004000000000080000000000000000000000000000000000010100000000000000000000000000000000020000000000000000000000000000000000080000000000000000000000000000040004000000000000002002002000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000200000200000010").into(),
|
||||
prev_randao: hex!("62e309d4f5119d1f5c783abc20fc1a549efbab546d8d0b25ff1cfd58be524e67").into(),
|
||||
block_number: 393,
|
||||
gas_limit: 54492273,
|
||||
gas_used: 199644,
|
||||
timestamp: 1710552813,
|
||||
extra_data: hex!("d983010d0b846765746888676f312e32312e368664617277696e").into(),
|
||||
base_fee_per_gas: U256::from(7u64),
|
||||
block_hash: hex!("48498dbfbcfae53a7f4c289ee00747aceea925f6260c50ead5a33e1c55c40f98").into(),
|
||||
transactions_root: hex!("5ebc1347fe3df0611d4f66b19bd8e1c6f4eaed0371d850f14c83b1c77ea234e6").into(),
|
||||
block_hash: hex!("6a9810efb9581d30c1a5c9074f27c68ea779a8c1ae31c213241df16225f4e131").into(),
|
||||
transactions_root: hex!("2cfa6ed7327e8807c7973516c5c32a68ef2459e586e8067e113d081c3bd8c07d").into(),
|
||||
withdrawals_root: hex!("792930bbd5baac43bcc798ee49aa8185ef76bb3b44ba62b91d86ae569e4bb535").into(),
|
||||
blob_gas_used: 0,
|
||||
excess_blob_gas: 0,
|
||||
}),
|
||||
execution_branch: vec![
|
||||
hex!("f8c69d3830406d668619bcccc13c8dddde41e863326f7418b241d5924c4ad34a").into(),
|
||||
hex!("a6833fa629f3286b6916c6e50b8bf089fc9126bee6f64d0413b4e59c1265834d").into(),
|
||||
hex!("b46f0c01805fe212e15907981b757e6c496b0cb06664224655613dcec82505bb").into(),
|
||||
hex!("db56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71").into(),
|
||||
hex!("f4d6b5cf9c6e212615c3674fa625d04eb1114153fb221ef5ad02aa433fc67cfb").into(),
|
||||
hex!("d3af7c05c516726be7505239e0b9c7cb53d24abce6b91cdb3b3995f0164a75da").into(),
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
pub fn make_inbound_fixture() -> InboundQueueFixture {
|
||||
InboundQueueFixture {
|
||||
message: Message {
|
||||
event_log: Log {
|
||||
address: hex!("eda338e4dc46038493b885327842fd3e301cab39").into(),
|
||||
topics: vec![
|
||||
hex!("7153f9357c8ea496bba60bf82e67143e27b64462b49041f8e689e1b05728f84f").into(),
|
||||
hex!("c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539").into(),
|
||||
hex!("5f7060e971b0dc81e63f0aa41831091847d97c1a4693ac450cc128c7214e65e0").into(),
|
||||
],
|
||||
data: hex!("00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002e00a736aa00000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d00e40b54020000000000000000000000000000000000000000000000000000000000").into(),
|
||||
},
|
||||
proof: Proof {
|
||||
receipt_proof: (vec![
|
||||
hex!("dccdfceea05036f7b61dcdabadc937945d31e68a8d3dfd4dc85684457988c284").to_vec(),
|
||||
hex!("4a98e45a319168b0fc6005ce6b744ee9bf54338e2c0784b976a8578d241ced0f").to_vec(),
|
||||
], vec![
|
||||
hex!("f851a09c01dd6d2d8de951c45af23d3ad00829ce021c04d6c8acbe1612d456ee320d4980808080808080a04a98e45a319168b0fc6005ce6b744ee9bf54338e2c0784b976a8578d241ced0f8080808080808080").to_vec(),
|
||||
hex!("f9028c30b9028802f90284018301d205b9010000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000080000000000000000000000000000004000000000080000000000000000000000000000000000010100000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000040004000000000000002000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000200000000000010f90179f85894eda338e4dc46038493b885327842fd3e301cab39e1a0f78bb28d4b1d7da699e5c0bc2be29c2b04b5aab6aacf6298fe5304f9db9c6d7ea000000000000000000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7df9011c94eda338e4dc46038493b885327842fd3e301cab39f863a07153f9357c8ea496bba60bf82e67143e27b64462b49041f8e689e1b05728f84fa0c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539a05f7060e971b0dc81e63f0aa41831091847d97c1a4693ac450cc128c7214e65e0b8a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002e00a736aa00000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d00e40b54020000000000000000000000000000000000000000000000000000000000").to_vec(),
|
||||
]),
|
||||
execution_proof: ExecutionProof {
|
||||
header: BeaconHeader {
|
||||
slot: 393,
|
||||
proposer_index: 4,
|
||||
parent_root: hex!("6545b47a614a1dd4cad042a0cdbbf5be347e8ffcdc02c6c64540d5153acebeef").into(),
|
||||
state_root: hex!("b62ac34a8cb82497be9542fe2114410c9f6021855b766015406101a1f3d86434").into(),
|
||||
body_root: hex!("04005fe231e11a5b7b1580cb73b177ae8b338bedd745497e6bb7122126a806db").into(),
|
||||
},
|
||||
ancestry_proof: Some(AncestryProof {
|
||||
header_branch: vec![
|
||||
hex!("6545b47a614a1dd4cad042a0cdbbf5be347e8ffcdc02c6c64540d5153acebeef").into(),
|
||||
hex!("fa84cc88ca53a72181599ff4eb07d8b444bce023fe2347c3b4f51004c43439d3").into(),
|
||||
hex!("cadc8ae211c6f2221c9138e829249adf902419c78eb4727a150baa4d9a02cc9d").into(),
|
||||
hex!("33a89962df08a35c52bd7e1d887cd71fa7803e68787d05c714036f6edf75947c").into(),
|
||||
hex!("2c9760fce5c2829ef3f25595a703c21eb22d0186ce223295556ed5da663a82cf").into(),
|
||||
hex!("e1aa87654db79c8a0ecd6c89726bb662fcb1684badaef5cd5256f479e3c622e1").into(),
|
||||
hex!("aa70d5f314e4a1fbb9c362f3db79b21bf68b328887248651fbd29fc501d0ca97").into(),
|
||||
hex!("160b6c235b3a1ed4ef5f80b03ee1c76f7bf3f591c92fca9d8663e9221b9f9f0f").into(),
|
||||
hex!("f68d7dcd6a07a18e9de7b5d2aa1980eb962e11d7dcb584c96e81a7635c8d2535").into(),
|
||||
hex!("1d5f912dfd6697110dd1ecb5cb8e77952eef57d85deb373572572df62bb157fc").into(),
|
||||
hex!("ffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b").into(),
|
||||
hex!("6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220").into(),
|
||||
hex!("b7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f").into(),
|
||||
],
|
||||
finalized_block_root: hex!("751414cd97c0624f922b3e80285e9f776b08fa22fd5f87391f2ed7ef571a8d46").into(),
|
||||
}),
|
||||
execution_header: VersionedExecutionPayloadHeader::Deneb(deneb::ExecutionPayloadHeader {
|
||||
parent_hash: hex!("8092290aa21b7751576440f77edd02a94058429ce50e63a92d620951fb25eda2").into(),
|
||||
fee_recipient: hex!("0000000000000000000000000000000000000000").into(),
|
||||
state_root: hex!("96a83e9ddf745346fafcb0b03d57314623df669ed543c110662b21302a0fae8b").into(),
|
||||
receipts_root: hex!("dccdfceea05036f7b61dcdabadc937945d31e68a8d3dfd4dc85684457988c284").into(),
|
||||
logs_bloom: hex!("00000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000080000000400000000000000000000004000000000080000000000000000000000000000000000010100000000000000000000000000000000020000000000000000000000000000000000080000000000000000000000000000040004000000000000002002002000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000200000200000010").into(),
|
||||
prev_randao: hex!("62e309d4f5119d1f5c783abc20fc1a549efbab546d8d0b25ff1cfd58be524e67").into(),
|
||||
block_number: 393,
|
||||
gas_limit: 54492273,
|
||||
gas_used: 199644,
|
||||
timestamp: 1710552813,
|
||||
extra_data: hex!("d983010d0b846765746888676f312e32312e368664617277696e").into(),
|
||||
base_fee_per_gas: U256::from(7u64),
|
||||
block_hash: hex!("6a9810efb9581d30c1a5c9074f27c68ea779a8c1ae31c213241df16225f4e131").into(),
|
||||
transactions_root: hex!("2cfa6ed7327e8807c7973516c5c32a68ef2459e586e8067e113d081c3bd8c07d").into(),
|
||||
withdrawals_root: hex!("792930bbd5baac43bcc798ee49aa8185ef76bb3b44ba62b91d86ae569e4bb535").into(),
|
||||
blob_gas_used: 0,
|
||||
excess_blob_gas: 0,
|
||||
}),
|
||||
execution_branch: vec![
|
||||
hex!("a6833fa629f3286b6916c6e50b8bf089fc9126bee6f64d0413b4e59c1265834d").into(),
|
||||
hex!("b46f0c01805fe212e15907981b757e6c496b0cb06664224655613dcec82505bb").into(),
|
||||
hex!("db56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71").into(),
|
||||
hex!("d3af7c05c516726be7505239e0b9c7cb53d24abce6b91cdb3b3995f0164a75da").into(),
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
finalized_header: BeaconHeader {
|
||||
slot: 864,
|
||||
proposer_index: 4,
|
||||
parent_root: hex!("614e7672f991ac268cd841055973f55e1e42228831a211adef207bb7329be614").into(),
|
||||
state_root: hex!("5fa8dfca3d760e4242ab46d529144627aa85348a19173b6e081172c701197a4a").into(),
|
||||
body_root: hex!("0f34c083b1803666bb1ac5e73fa71582731a2cf37d279ff0a3b0cad5a2ff371e").into(),
|
||||
},
|
||||
block_roots_root: hex!("b9aab9c388c4e4fcd899b71f62c498fc73406e38e8eb14aa440e9affa06f2a10").into(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,24 +65,6 @@ mod benchmarks {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark]
|
||||
fn submit_execution_header() -> Result<(), BenchmarkError> {
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
let checkpoint_update = make_checkpoint();
|
||||
let finalized_header_update = make_finalized_header_update();
|
||||
let execution_header_update = make_execution_header_update();
|
||||
let execution_header_hash = execution_header_update.execution_header.block_hash();
|
||||
EthereumBeaconClient::<T>::process_checkpoint_update(&checkpoint_update)?;
|
||||
EthereumBeaconClient::<T>::process_update(&finalized_header_update)?;
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Signed(caller.clone()), Box::new(*execution_header_update));
|
||||
|
||||
assert!(<ExecutionHeaders<T>>::contains_key(execution_header_hash));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[benchmark(extra)]
|
||||
fn bls_fast_aggregate_verify_pre_aggregated() -> Result<(), BenchmarkError> {
|
||||
EthereumBeaconClient::<T>::process_checkpoint_update(&make_checkpoint())?;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
|
||||
use super::*;
|
||||
use frame_support::ensure;
|
||||
use primitives::ExecutionProof;
|
||||
|
||||
use snowbridge_core::inbound::{
|
||||
VerificationError::{self, *},
|
||||
@@ -14,32 +16,13 @@ impl<T: Config> Verifier for Pallet<T> {
|
||||
/// the log should be in the beacon client storage, meaning it has been verified and is an
|
||||
/// ancestor of a finalized beacon block.
|
||||
fn verify(event_log: &Log, proof: &Proof) -> Result<(), VerificationError> {
|
||||
log::info!(
|
||||
target: "ethereum-client",
|
||||
"💫 Verifying message with block hash {}",
|
||||
proof.block_hash,
|
||||
);
|
||||
Self::verify_execution_proof(&proof.execution_proof)
|
||||
.map_err(|e| InvalidExecutionProof(e.into()))?;
|
||||
|
||||
let header = <ExecutionHeaderBuffer<T>>::get(proof.block_hash).ok_or(HeaderNotFound)?;
|
||||
|
||||
let receipt = match Self::verify_receipt_inclusion(header.receipts_root, proof) {
|
||||
Ok(receipt) => receipt,
|
||||
Err(err) => {
|
||||
log::error!(
|
||||
target: "ethereum-client",
|
||||
"💫 Verification of receipt inclusion failed for block {}: {:?}",
|
||||
proof.block_hash,
|
||||
err
|
||||
);
|
||||
return Err(err)
|
||||
},
|
||||
};
|
||||
|
||||
log::trace!(
|
||||
target: "ethereum-client",
|
||||
"💫 Verified receipt inclusion for transaction at index {} in block {}",
|
||||
proof.tx_index, proof.block_hash,
|
||||
);
|
||||
let receipt = Self::verify_receipt_inclusion(
|
||||
proof.execution_proof.execution_header.receipts_root(),
|
||||
&proof.receipt_proof.1,
|
||||
)?;
|
||||
|
||||
event_log.validate().map_err(|_| InvalidLog)?;
|
||||
|
||||
@@ -53,18 +36,11 @@ impl<T: Config> Verifier for Pallet<T> {
|
||||
if !receipt.contains_log(&event_log) {
|
||||
log::error!(
|
||||
target: "ethereum-client",
|
||||
"💫 Event log not found in receipt for transaction at index {} in block {}",
|
||||
proof.tx_index, proof.block_hash,
|
||||
"💫 Event log not found in receipt for transaction",
|
||||
);
|
||||
return Err(LogNotFound)
|
||||
}
|
||||
|
||||
log::info!(
|
||||
target: "ethereum-client",
|
||||
"💫 Receipt verification successful for {}",
|
||||
proof.block_hash,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -74,9 +50,9 @@ impl<T: Config> Pallet<T> {
|
||||
/// `proof.block_hash`.
|
||||
pub fn verify_receipt_inclusion(
|
||||
receipts_root: H256,
|
||||
proof: &Proof,
|
||||
receipt_proof: &[Vec<u8>],
|
||||
) -> Result<Receipt, VerificationError> {
|
||||
let result = verify_receipt_proof(receipts_root, &proof.data.1).ok_or(InvalidProof)?;
|
||||
let result = verify_receipt_proof(receipts_root, receipt_proof).ok_or(InvalidProof)?;
|
||||
|
||||
match result {
|
||||
Ok(receipt) => Ok(receipt),
|
||||
@@ -90,4 +66,96 @@ impl<T: Config> Pallet<T> {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Validates an execution header with ancestry_proof against a finalized checkpoint on
|
||||
/// chain.The beacon header containing the execution header is sent, plus the execution header,
|
||||
/// along with a proof that the execution header is rooted in the beacon header body.
|
||||
pub(crate) fn verify_execution_proof(execution_proof: &ExecutionProof) -> DispatchResult {
|
||||
let latest_finalized_state =
|
||||
FinalizedBeaconState::<T>::get(LatestFinalizedBlockRoot::<T>::get())
|
||||
.ok_or(Error::<T>::NotBootstrapped)?;
|
||||
// Checks that the header is an ancestor of a finalized header, using slot number.
|
||||
ensure!(
|
||||
execution_proof.header.slot <= latest_finalized_state.slot,
|
||||
Error::<T>::HeaderNotFinalized
|
||||
);
|
||||
|
||||
// Gets the hash tree root of the execution header, in preparation for the execution
|
||||
// header proof (used to check that the execution header is rooted in the beacon
|
||||
// header body.
|
||||
let execution_header_root: H256 = execution_proof
|
||||
.execution_header
|
||||
.hash_tree_root()
|
||||
.map_err(|_| Error::<T>::BlockBodyHashTreeRootFailed)?;
|
||||
|
||||
ensure!(
|
||||
verify_merkle_branch(
|
||||
execution_header_root,
|
||||
&execution_proof.execution_branch,
|
||||
config::EXECUTION_HEADER_SUBTREE_INDEX,
|
||||
config::EXECUTION_HEADER_DEPTH,
|
||||
execution_proof.header.body_root
|
||||
),
|
||||
Error::<T>::InvalidExecutionHeaderProof
|
||||
);
|
||||
|
||||
let beacon_block_root: H256 = execution_proof
|
||||
.header
|
||||
.hash_tree_root()
|
||||
.map_err(|_| Error::<T>::HeaderHashTreeRootFailed)?;
|
||||
|
||||
match &execution_proof.ancestry_proof {
|
||||
Some(proof) => {
|
||||
Self::verify_ancestry_proof(
|
||||
beacon_block_root,
|
||||
execution_proof.header.slot,
|
||||
&proof.header_branch,
|
||||
proof.finalized_block_root,
|
||||
)?;
|
||||
},
|
||||
None => {
|
||||
// If the ancestry proof is not provided, we expect this beacon header to be a
|
||||
// finalized beacon header. We need to check that the header hash matches the
|
||||
// finalized header root at the expected slot.
|
||||
let state = <FinalizedBeaconState<T>>::get(beacon_block_root)
|
||||
.ok_or(Error::<T>::ExpectedFinalizedHeaderNotStored)?;
|
||||
if execution_proof.header.slot != state.slot {
|
||||
return Err(Error::<T>::ExpectedFinalizedHeaderNotStored.into())
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Verify that `block_root` is an ancestor of `finalized_block_root` Used to prove that
|
||||
/// an execution header is an ancestor of a finalized header (i.e. the blocks are
|
||||
/// on the same chain).
|
||||
fn verify_ancestry_proof(
|
||||
block_root: H256,
|
||||
block_slot: u64,
|
||||
block_root_proof: &[H256],
|
||||
finalized_block_root: H256,
|
||||
) -> DispatchResult {
|
||||
let state = <FinalizedBeaconState<T>>::get(finalized_block_root)
|
||||
.ok_or(Error::<T>::ExpectedFinalizedHeaderNotStored)?;
|
||||
|
||||
ensure!(block_slot < state.slot, Error::<T>::HeaderNotFinalized);
|
||||
|
||||
let index_in_array = block_slot % (SLOTS_PER_HISTORICAL_ROOT as u64);
|
||||
let leaf_index = (SLOTS_PER_HISTORICAL_ROOT as u64) + index_in_array;
|
||||
|
||||
ensure!(
|
||||
verify_merkle_branch(
|
||||
block_root,
|
||||
block_root_proof,
|
||||
leaf_index as usize,
|
||||
config::BLOCK_ROOT_AT_INDEX_DEPTH,
|
||||
state.block_roots_root
|
||||
),
|
||||
Error::<T>::InvalidAncestryMerkleProof
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
//! ## Consensus Updates
|
||||
//!
|
||||
//! * [`Call::submit`]: Submit a finalized beacon header with an optional sync committee update
|
||||
//! * [`Call::submit_execution_header`]: Submit an execution header together with an ancestry proof
|
||||
//! that can be verified against an already imported finalized beacon header.
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
pub mod config;
|
||||
@@ -40,8 +38,7 @@ use frame_support::{
|
||||
use frame_system::ensure_signed;
|
||||
use primitives::{
|
||||
fast_aggregate_verify, verify_merkle_branch, verify_receipt_proof, BeaconHeader, BlsError,
|
||||
CompactBeaconState, CompactExecutionHeader, ExecutionHeaderState, ForkData, ForkVersion,
|
||||
ForkVersions, PublicKeyPrepared, SigningData,
|
||||
CompactBeaconState, ForkData, ForkVersion, ForkVersions, PublicKeyPrepared, SigningData,
|
||||
};
|
||||
use snowbridge_core::{BasicOperatingMode, RingBufferMap};
|
||||
use sp_core::H256;
|
||||
@@ -51,11 +48,7 @@ pub use weights::WeightInfo;
|
||||
use functions::{
|
||||
compute_epoch, compute_period, decompress_sync_committee_bits, sync_committee_sum,
|
||||
};
|
||||
pub use types::ExecutionHeaderBuffer;
|
||||
use types::{
|
||||
CheckpointUpdate, ExecutionHeaderUpdate, FinalizedBeaconStateBuffer, SyncCommitteePrepared,
|
||||
Update,
|
||||
};
|
||||
use types::{CheckpointUpdate, FinalizedBeaconStateBuffer, SyncCommitteePrepared, Update};
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
@@ -76,10 +69,7 @@ pub mod pallet {
|
||||
pub struct MaxFinalizedHeadersToKeep<T: Config>(PhantomData<T>);
|
||||
impl<T: Config> Get<u32> for MaxFinalizedHeadersToKeep<T> {
|
||||
fn get() -> u32 {
|
||||
// Consider max latency allowed between LatestFinalizedState and LatestExecutionState is
|
||||
// the total slots in one sync_committee_period so 1 should be fine we keep 2 periods
|
||||
// here for redundancy.
|
||||
const MAX_REDUNDANCY: u32 = 2;
|
||||
const MAX_REDUNDANCY: u32 = 20;
|
||||
config::EPOCHS_PER_SYNC_COMMITTEE_PERIOD as u32 * MAX_REDUNDANCY
|
||||
}
|
||||
}
|
||||
@@ -92,9 +82,6 @@ pub mod pallet {
|
||||
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
||||
#[pallet::constant]
|
||||
type ForkVersions: Get<ForkVersions>;
|
||||
/// Maximum number of execution headers to keep
|
||||
#[pallet::constant]
|
||||
type MaxExecutionHeadersToKeep: Get<u32>;
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
|
||||
@@ -105,10 +92,6 @@ pub mod pallet {
|
||||
block_hash: H256,
|
||||
slot: u64,
|
||||
},
|
||||
ExecutionHeaderImported {
|
||||
block_hash: H256,
|
||||
block_number: u64,
|
||||
},
|
||||
SyncCommitteeUpdated {
|
||||
period: u64,
|
||||
},
|
||||
@@ -191,25 +174,6 @@ pub mod pallet {
|
||||
pub(super) type NextSyncCommittee<T: Config> =
|
||||
StorageValue<_, SyncCommitteePrepared, ValueQuery>;
|
||||
|
||||
/// Latest imported execution header
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn latest_execution_state)]
|
||||
pub(super) type LatestExecutionState<T: Config> =
|
||||
StorageValue<_, ExecutionHeaderState, ValueQuery>;
|
||||
|
||||
/// Execution Headers
|
||||
#[pallet::storage]
|
||||
pub type ExecutionHeaders<T: Config> =
|
||||
StorageMap<_, Identity, H256, CompactExecutionHeader, OptionQuery>;
|
||||
|
||||
/// Execution Headers: Current position in ring buffer
|
||||
#[pallet::storage]
|
||||
pub type ExecutionHeaderIndex<T: Config> = StorageValue<_, u32, ValueQuery>;
|
||||
|
||||
/// Execution Headers: Mapping of ring buffer index to a pruning candidate
|
||||
#[pallet::storage]
|
||||
pub type ExecutionHeaderMapping<T: Config> = StorageMap<_, Identity, u32, H256, ValueQuery>;
|
||||
|
||||
/// The current operating mode of the pallet.
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn operating_mode)]
|
||||
@@ -248,21 +212,6 @@ pub mod pallet {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pallet::call_index(2)]
|
||||
#[pallet::weight(T::WeightInfo::submit_execution_header())]
|
||||
#[transactional]
|
||||
/// Submits a new execution header update. The relevant related beacon header
|
||||
/// is also included to prove the execution header, as well as ancestry proof data.
|
||||
pub fn submit_execution_header(
|
||||
origin: OriginFor<T>,
|
||||
update: Box<ExecutionHeaderUpdate>,
|
||||
) -> DispatchResult {
|
||||
ensure_signed(origin)?;
|
||||
ensure!(!Self::operating_mode().is_halted(), Error::<T>::Halted);
|
||||
Self::process_execution_header_update(&update)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Halt or resume all pallet operations. May only be called by root.
|
||||
#[pallet::call_index(3)]
|
||||
#[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))]
|
||||
@@ -325,41 +274,19 @@ pub mod pallet {
|
||||
<CurrentSyncCommittee<T>>::set(sync_committee_prepared);
|
||||
<NextSyncCommittee<T>>::kill();
|
||||
InitialCheckpointRoot::<T>::set(header_root);
|
||||
<LatestExecutionState<T>>::kill();
|
||||
|
||||
Self::store_validators_root(update.validators_root);
|
||||
Self::store_finalized_header(header_root, update.header, update.block_roots_root)?;
|
||||
Self::store_finalized_header(update.header, update.block_roots_root)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn process_update(update: &Update) -> DispatchResult {
|
||||
Self::cross_check_execution_state()?;
|
||||
Self::verify_update(update)?;
|
||||
Self::apply_update(update)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Cross check to make sure that execution header import does not fall too far behind
|
||||
/// finalised beacon header import. If that happens just return an error and pause
|
||||
/// processing until execution header processing has caught up.
|
||||
pub(crate) fn cross_check_execution_state() -> DispatchResult {
|
||||
let latest_finalized_state =
|
||||
FinalizedBeaconState::<T>::get(LatestFinalizedBlockRoot::<T>::get())
|
||||
.ok_or(Error::<T>::NotBootstrapped)?;
|
||||
let latest_execution_state = Self::latest_execution_state();
|
||||
// The execution header import should be at least within the slot range of a sync
|
||||
// committee period.
|
||||
let max_latency = config::EPOCHS_PER_SYNC_COMMITTEE_PERIOD * config::SLOTS_PER_EPOCH;
|
||||
ensure!(
|
||||
latest_execution_state.beacon_slot == 0 ||
|
||||
latest_finalized_state.slot <
|
||||
latest_execution_state.beacon_slot + max_latency as u64,
|
||||
Error::<T>::ExecutionHeaderTooFarBehind
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// References and strictly follows <https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#validate_light_client_update>
|
||||
/// Verifies that provided next sync committee is valid through a series of checks
|
||||
/// (including checking that a sync committee period isn't skipped and that the header is
|
||||
@@ -534,130 +461,12 @@ pub mod pallet {
|
||||
};
|
||||
|
||||
if update.finalized_header.slot > latest_finalized_state.slot {
|
||||
let finalized_block_root: H256 = update
|
||||
.finalized_header
|
||||
.hash_tree_root()
|
||||
.map_err(|_| Error::<T>::HeaderHashTreeRootFailed)?;
|
||||
Self::store_finalized_header(
|
||||
finalized_block_root,
|
||||
update.finalized_header,
|
||||
update.block_roots_root,
|
||||
)?;
|
||||
Self::store_finalized_header(update.finalized_header, update.block_roots_root)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validates an execution header for import. The beacon header containing the execution
|
||||
/// header is sent, plus the execution header, along with a proof that the execution header
|
||||
/// is rooted in the beacon header body.
|
||||
pub(crate) fn process_execution_header_update(
|
||||
update: &ExecutionHeaderUpdate,
|
||||
) -> DispatchResult {
|
||||
let latest_finalized_state =
|
||||
FinalizedBeaconState::<T>::get(LatestFinalizedBlockRoot::<T>::get())
|
||||
.ok_or(Error::<T>::NotBootstrapped)?;
|
||||
// Checks that the header is an ancestor of a finalized header, using slot number.
|
||||
ensure!(
|
||||
update.header.slot <= latest_finalized_state.slot,
|
||||
Error::<T>::HeaderNotFinalized
|
||||
);
|
||||
|
||||
// Checks that we don't skip execution headers, they need to be imported sequentially.
|
||||
let latest_execution_state: ExecutionHeaderState = Self::latest_execution_state();
|
||||
ensure!(
|
||||
latest_execution_state.block_number == 0 ||
|
||||
update.execution_header.block_number() ==
|
||||
latest_execution_state.block_number + 1,
|
||||
Error::<T>::ExecutionHeaderSkippedBlock
|
||||
);
|
||||
|
||||
// Gets the hash tree root of the execution header, in preparation for the execution
|
||||
// header proof (used to check that the execution header is rooted in the beacon
|
||||
// header body.
|
||||
let execution_header_root: H256 = update
|
||||
.execution_header
|
||||
.hash_tree_root()
|
||||
.map_err(|_| Error::<T>::BlockBodyHashTreeRootFailed)?;
|
||||
|
||||
ensure!(
|
||||
verify_merkle_branch(
|
||||
execution_header_root,
|
||||
&update.execution_branch,
|
||||
config::EXECUTION_HEADER_SUBTREE_INDEX,
|
||||
config::EXECUTION_HEADER_DEPTH,
|
||||
update.header.body_root
|
||||
),
|
||||
Error::<T>::InvalidExecutionHeaderProof
|
||||
);
|
||||
|
||||
let block_root: H256 = update
|
||||
.header
|
||||
.hash_tree_root()
|
||||
.map_err(|_| Error::<T>::HeaderHashTreeRootFailed)?;
|
||||
|
||||
match &update.ancestry_proof {
|
||||
Some(proof) => {
|
||||
Self::verify_ancestry_proof(
|
||||
block_root,
|
||||
update.header.slot,
|
||||
&proof.header_branch,
|
||||
proof.finalized_block_root,
|
||||
)?;
|
||||
},
|
||||
None => {
|
||||
// If the ancestry proof is not provided, we expect this header to be a
|
||||
// finalized header. We need to check that the header hash matches the finalized
|
||||
// header root at the expected slot.
|
||||
let state = <FinalizedBeaconState<T>>::get(block_root)
|
||||
.ok_or(Error::<T>::ExpectedFinalizedHeaderNotStored)?;
|
||||
if update.header.slot != state.slot {
|
||||
return Err(Error::<T>::ExpectedFinalizedHeaderNotStored.into())
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Self::store_execution_header(
|
||||
update.execution_header.block_hash(),
|
||||
update.execution_header.clone().into(),
|
||||
update.header.slot,
|
||||
block_root,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Verify that `block_root` is an ancestor of `finalized_block_root` Used to prove that
|
||||
/// an execution header is an ancestor of a finalized header (i.e. the blocks are
|
||||
/// on the same chain).
|
||||
fn verify_ancestry_proof(
|
||||
block_root: H256,
|
||||
block_slot: u64,
|
||||
block_root_proof: &[H256],
|
||||
finalized_block_root: H256,
|
||||
) -> DispatchResult {
|
||||
let state = <FinalizedBeaconState<T>>::get(finalized_block_root)
|
||||
.ok_or(Error::<T>::ExpectedFinalizedHeaderNotStored)?;
|
||||
|
||||
ensure!(block_slot < state.slot, Error::<T>::HeaderNotFinalized);
|
||||
|
||||
let index_in_array = block_slot % (SLOTS_PER_HISTORICAL_ROOT as u64);
|
||||
let leaf_index = (SLOTS_PER_HISTORICAL_ROOT as u64) + index_in_array;
|
||||
|
||||
ensure!(
|
||||
verify_merkle_branch(
|
||||
block_root,
|
||||
block_root_proof,
|
||||
leaf_index as usize,
|
||||
config::BLOCK_ROOT_AT_INDEX_DEPTH,
|
||||
state.block_roots_root
|
||||
),
|
||||
Error::<T>::InvalidAncestryMerkleProof
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Computes the signing root for a given beacon header and domain. The hash tree root
|
||||
/// of the beacon header is computed, and then the combination of the beacon header hash
|
||||
/// and the domain makes up the signing root.
|
||||
@@ -679,13 +488,15 @@ pub mod pallet {
|
||||
/// Stores a compacted (slot and block roots root (hash of the `block_roots` beacon state
|
||||
/// field, used for ancestry proof)) beacon state in a ring buffer map, with the header root
|
||||
/// as map key.
|
||||
fn store_finalized_header(
|
||||
header_root: H256,
|
||||
pub fn store_finalized_header(
|
||||
header: BeaconHeader,
|
||||
block_roots_root: H256,
|
||||
) -> DispatchResult {
|
||||
let slot = header.slot;
|
||||
|
||||
let header_root: H256 =
|
||||
header.hash_tree_root().map_err(|_| Error::<T>::HeaderHashTreeRootFailed)?;
|
||||
|
||||
<FinalizedBeaconStateBuffer<T>>::insert(
|
||||
header_root,
|
||||
CompactBeaconState { slot: header.slot, block_roots_root },
|
||||
@@ -704,36 +515,6 @@ pub mod pallet {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Stores the provided execution header in pallet storage. The header is stored
|
||||
/// in a ring buffer map, with the block hash as map key. The last imported execution
|
||||
/// header is also kept in storage, for the relayer to check import progress.
|
||||
pub fn store_execution_header(
|
||||
block_hash: H256,
|
||||
header: CompactExecutionHeader,
|
||||
beacon_slot: u64,
|
||||
beacon_block_root: H256,
|
||||
) {
|
||||
let block_number = header.block_number;
|
||||
|
||||
<ExecutionHeaderBuffer<T>>::insert(block_hash, header);
|
||||
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"💫 Updated latest execution block at {} to number {}.",
|
||||
block_hash,
|
||||
block_number
|
||||
);
|
||||
|
||||
LatestExecutionState::<T>::mutate(|s| {
|
||||
s.beacon_block_root = beacon_block_root;
|
||||
s.beacon_slot = beacon_slot;
|
||||
s.block_hash = block_hash;
|
||||
s.block_number = block_number;
|
||||
});
|
||||
|
||||
Self::deposit_event(Event::ExecutionHeaderImported { block_hash, block_number });
|
||||
}
|
||||
|
||||
/// Stores the validators root in storage. Validators root is the hash tree root of all the
|
||||
/// validators at genesis and is used to used to identify the chain that we are on
|
||||
/// (used in conjunction with the fork version).
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
|
||||
use crate as ethereum_beacon_client;
|
||||
use crate::config;
|
||||
use frame_support::{derive_impl, parameter_types};
|
||||
use hex_literal::hex;
|
||||
use frame_support::{derive_impl, dispatch::DispatchResult, parameter_types};
|
||||
use pallet_timestamp;
|
||||
use primitives::{CompactExecutionHeader, Fork, ForkVersions};
|
||||
use primitives::{Fork, ForkVersions};
|
||||
use snowbridge_core::inbound::{Log, Proof};
|
||||
use sp_std::default::Default;
|
||||
use std::{fs::File, path::PathBuf};
|
||||
|
||||
type Block = frame_system::mocking::MockBlock<Test>;
|
||||
use sp_runtime::BuildStorage;
|
||||
|
||||
@@ -20,8 +21,8 @@ where
|
||||
serde_json::from_reader(File::open(filepath).unwrap())
|
||||
}
|
||||
|
||||
pub fn load_execution_header_update_fixture() -> primitives::ExecutionHeaderUpdate {
|
||||
load_fixture("execution-header-update.json".to_string()).unwrap()
|
||||
pub fn load_execution_proof_fixture() -> primitives::ExecutionProof {
|
||||
load_fixture("execution-proof.json".to_string()).unwrap()
|
||||
}
|
||||
|
||||
pub fn load_checkpoint_update_fixture(
|
||||
@@ -50,41 +51,8 @@ pub fn load_next_finalized_header_update_fixture(
|
||||
}
|
||||
|
||||
pub fn get_message_verification_payload() -> (Log, Proof) {
|
||||
(
|
||||
Log {
|
||||
address: hex!("ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0").into(),
|
||||
topics: vec![
|
||||
hex!("1b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ad").into(),
|
||||
hex!("00000000000000000000000000000000000000000000000000000000000003e8").into(),
|
||||
hex!("0000000000000000000000000000000000000000000000000000000000000001").into(),
|
||||
],
|
||||
data: hex!("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b000f000000000000000100d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec701345772617070656420457468657210574554481235003511000000000000000000000000000000000000000000").into(),
|
||||
},
|
||||
Proof {
|
||||
block_hash: hex!("05aaa60b0f27cce9e71909508527264b77ee14da7b5bf915fcc4e32715333213").into(),
|
||||
tx_index: 0,
|
||||
data: (vec![
|
||||
hex!("cf0d1c1ba57d1e0edfb59786c7e30c2b7e12bd54612b00cd21c4eaeecedf44fb").to_vec(),
|
||||
hex!("d21fc4f68ab05bc4dcb23c67008e92c4d466437cdd6ed7aad0c008944c185510").to_vec(),
|
||||
hex!("b9890f91ca0d77aa2a4adfaf9b9e40c94cac9e638b6d9797923865872944b646").to_vec(),
|
||||
], vec![
|
||||
hex!("f90131a0b601337b3aa10a671caa724eba641e759399979856141d3aea6b6b4ac59b889ba00c7d5dd48be9060221a02fb8fa213860b4c50d47046c8fa65ffaba5737d569e0a094601b62a1086cd9c9cb71a7ebff9e718f3217fd6e837efe4246733c0a196f63a06a4b0dd0aefc37b3c77828c8f07d1b7a2455ceb5dbfd3c77d7d6aeeddc2f7e8ca0d6e8e23142cdd8ec219e1f5d8b56aa18e456702b195deeaa210327284d42ade4a08a313d4c87023005d1ab631bbfe3f5de1e405d0e66d0bef3e033f1e5711b5521a0bf09a5d9a48b10ade82b8d6a5362a15921c8b5228a3487479b467db97411d82fa0f95cccae2a7c572ef3c566503e30bac2b2feb2d2f26eebf6d870dcf7f8cf59cea0d21fc4f68ab05bc4dcb23c67008e92c4d466437cdd6ed7aad0c008944c1855108080808080808080").to_vec(),
|
||||
hex!("f851a0b9890f91ca0d77aa2a4adfaf9b9e40c94cac9e638b6d9797923865872944b646a060a634b9280e3a23fb63375e7bbdd9ab07fd379ab6a67e2312bbc112195fa358808080808080808080808080808080").to_vec(),
|
||||
hex!("f9030820b9030402f90300018301d6e2b9010000000000000800000000000020040008000000000000000000000000400000008000000000000000000000000000000000000000000000000000000000042010000000001000000000000000000000000000000000040000000000000000000000000000000000000000000000008000000000000000002000000000000000000000000200000000000000200000000000100000000040000001000200008000000000000200000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000f901f5f87a942ffa5ecdbe006d30397c7636d3e015eee251369ff842a0c965575a00553e094ca7c5d14f02e107c258dda06867cbf9e0e69f80e71bbcc1a000000000000000000000000000000000000000000000000000000000000003e8a000000000000000000000000000000000000000000000000000000000000003e8f9011c94ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0f863a01b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ada000000000000000000000000000000000000000000000000000000000000003e8a00000000000000000000000000000000000000000000000000000000000000001b8a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b000f000000000000000100d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec701345772617070656420457468657210574554481235003511000000000000000000000000000000000000000000f858948cf6147918a5cbb672703f879f385036f8793a24e1a01449abf21e49fd025f33495e77f7b1461caefdd3d4bb646424a3f445c4576a5ba0000000000000000000000000440edffa1352b13227e8ee646f3ea37456dec701").to_vec(),
|
||||
]),
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_message_verification_header() -> CompactExecutionHeader {
|
||||
CompactExecutionHeader {
|
||||
parent_hash: hex!("04a7f6ab8282203562c62f38b0ab41d32aaebe2c7ea687702b463148a6429e04")
|
||||
.into(),
|
||||
block_number: 55,
|
||||
state_root: hex!("894d968712976d613519f973a317cb0781c7b039c89f27ea2b7ca193f7befdb3").into(),
|
||||
receipts_root: hex!("cf0d1c1ba57d1e0edfb59786c7e30c2b7e12bd54612b00cd21c4eaeecedf44fb")
|
||||
.into(),
|
||||
}
|
||||
let inbound_fixture = snowbridge_pallet_ethereum_client_fixtures::make_inbound_fixture();
|
||||
(inbound_fixture.message.event_log, inbound_fixture.message.proof)
|
||||
}
|
||||
|
||||
frame_support::construct_runtime!(
|
||||
@@ -130,20 +98,25 @@ parameter_types! {
|
||||
epoch: 0,
|
||||
}
|
||||
};
|
||||
pub const ExecutionHeadersPruneThreshold: u32 = 8192;
|
||||
}
|
||||
|
||||
impl ethereum_beacon_client::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type ForkVersions = ChainForkVersions;
|
||||
type MaxExecutionHeadersToKeep = ExecutionHeadersPruneThreshold;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
// Build genesis storage according to the mock runtime.
|
||||
pub fn new_tester() -> sp_io::TestExternalities {
|
||||
let t = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
||||
let mut ext = sp_io::TestExternalities::new(t);
|
||||
let _ = ext.execute_with(|| Timestamp::set(RuntimeOrigin::signed(1), 30_000));
|
||||
let ext = sp_io::TestExternalities::new(t);
|
||||
ext
|
||||
}
|
||||
|
||||
pub fn initialize_storage() -> DispatchResult {
|
||||
let inbound_fixture = snowbridge_pallet_ethereum_client_fixtures::make_inbound_fixture();
|
||||
EthereumBeaconClient::store_finalized_header(
|
||||
inbound_fixture.finalized_header,
|
||||
inbound_fixture.block_roots_root,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
|
||||
use crate::{
|
||||
functions::compute_period, pallet::ExecutionHeaders, sync_committee_sum, verify_merkle_branch,
|
||||
BeaconHeader, CompactBeaconState, Error, ExecutionHeaderBuffer, FinalizedBeaconState,
|
||||
LatestExecutionState, LatestFinalizedBlockRoot, NextSyncCommittee, SyncCommitteePrepared,
|
||||
functions::compute_period, sync_committee_sum, verify_merkle_branch, BeaconHeader,
|
||||
CompactBeaconState, Error, FinalizedBeaconState, LatestFinalizedBlockRoot, NextSyncCommittee,
|
||||
SyncCommitteePrepared,
|
||||
};
|
||||
|
||||
use crate::mock::{
|
||||
get_message_verification_header, get_message_verification_payload,
|
||||
load_checkpoint_update_fixture, load_execution_header_update_fixture,
|
||||
get_message_verification_payload, load_checkpoint_update_fixture,
|
||||
load_finalized_header_update_fixture, load_next_finalized_header_update_fixture,
|
||||
load_next_sync_committee_update_fixture, load_sync_committee_update_fixture,
|
||||
};
|
||||
@@ -19,14 +18,9 @@ use crate::config::{EPOCHS_PER_SYNC_COMMITTEE_PERIOD, SLOTS_PER_EPOCH, SLOTS_PER
|
||||
use frame_support::{assert_err, assert_noop, assert_ok};
|
||||
use hex_literal::hex;
|
||||
use primitives::{
|
||||
CompactExecutionHeader, ExecutionHeaderState, Fork, ForkVersions, NextSyncCommitteeUpdate,
|
||||
VersionedExecutionPayloadHeader,
|
||||
};
|
||||
use rand::{thread_rng, Rng};
|
||||
use snowbridge_core::{
|
||||
inbound::{VerificationError, Verifier},
|
||||
RingBufferMap,
|
||||
types::deneb, Fork, ForkVersions, NextSyncCommitteeUpdate, VersionedExecutionPayloadHeader,
|
||||
};
|
||||
use snowbridge_core::inbound::{VerificationError, Verifier};
|
||||
use sp_core::H256;
|
||||
use sp_runtime::DispatchError;
|
||||
|
||||
@@ -212,61 +206,6 @@ pub fn sync_committee_participation_is_supermajority_errors_when_not_supermajori
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn execution_header_pruning() {
|
||||
new_tester().execute_with(|| {
|
||||
let execution_header_prune_threshold = ExecutionHeadersPruneThreshold::get();
|
||||
let to_be_deleted = execution_header_prune_threshold / 2;
|
||||
|
||||
let mut stored_hashes = vec![];
|
||||
|
||||
for i in 0..execution_header_prune_threshold {
|
||||
let mut hash = H256::default();
|
||||
thread_rng().try_fill(&mut hash.0[..]).unwrap();
|
||||
EthereumBeaconClient::store_execution_header(
|
||||
hash,
|
||||
CompactExecutionHeader::default(),
|
||||
i as u64,
|
||||
hash,
|
||||
);
|
||||
stored_hashes.push(hash);
|
||||
}
|
||||
|
||||
// We should have stored everything until now
|
||||
assert_eq!({ ExecutionHeaders::<Test>::iter().count() }, stored_hashes.len());
|
||||
|
||||
// Let's push extra entries so that some of the previous entries are deleted.
|
||||
for i in 0..to_be_deleted {
|
||||
let mut hash = H256::default();
|
||||
thread_rng().try_fill(&mut hash.0[..]).unwrap();
|
||||
EthereumBeaconClient::store_execution_header(
|
||||
hash,
|
||||
CompactExecutionHeader::default(),
|
||||
(i + execution_header_prune_threshold) as u64,
|
||||
hash,
|
||||
);
|
||||
|
||||
stored_hashes.push(hash);
|
||||
}
|
||||
|
||||
// We should have only stored up to `execution_header_prune_threshold`
|
||||
assert_eq!(
|
||||
ExecutionHeaders::<Test>::iter().count() as u32,
|
||||
execution_header_prune_threshold
|
||||
);
|
||||
|
||||
// First `to_be_deleted` items must be deleted
|
||||
for i in 0..to_be_deleted {
|
||||
assert!(!ExecutionHeaders::<Test>::contains_key(stored_hashes[i as usize]));
|
||||
}
|
||||
|
||||
// Other entries should be part of data
|
||||
for i in to_be_deleted..(to_be_deleted + execution_header_prune_threshold) {
|
||||
assert!(ExecutionHeaders::<Test>::contains_key(stored_hashes[i as usize]));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compute_fork_version() {
|
||||
let mock_fork_versions = ForkVersions {
|
||||
@@ -348,34 +287,6 @@ fn find_present_keys() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cross_check_execution_state() {
|
||||
new_tester().execute_with(|| {
|
||||
let header_root: H256 = TEST_HASH.into();
|
||||
<FinalizedBeaconState<Test>>::insert(
|
||||
header_root,
|
||||
CompactBeaconState {
|
||||
// set slot to period 5
|
||||
slot: ((EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH) * 5) as u64,
|
||||
block_roots_root: Default::default(),
|
||||
},
|
||||
);
|
||||
LatestFinalizedBlockRoot::<Test>::set(header_root);
|
||||
<LatestExecutionState<Test>>::set(ExecutionHeaderState {
|
||||
beacon_block_root: Default::default(),
|
||||
// set slot to period 2
|
||||
beacon_slot: ((EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH) * 2) as u64,
|
||||
block_hash: Default::default(),
|
||||
block_number: 0,
|
||||
});
|
||||
|
||||
assert_err!(
|
||||
EthereumBeaconClient::cross_check_execution_state(),
|
||||
Error::<Test>::ExecutionHeaderTooFarBehind
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/* SYNC PROCESS TESTS */
|
||||
|
||||
#[test]
|
||||
@@ -608,40 +519,6 @@ fn submit_update_with_skipped_sync_committee_period() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn submit_update_execution_headers_too_far_behind() {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
let finalized_header_update = Box::new(load_finalized_header_update_fixture());
|
||||
let execution_header_update = Box::new(load_execution_header_update_fixture());
|
||||
let next_update = Box::new(load_next_sync_committee_update_fixture());
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
let far_ahead_finalized_header_slot = finalized_header_update.finalized_header.slot +
|
||||
(EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH * 2) as u64;
|
||||
assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint));
|
||||
assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), finalized_header_update));
|
||||
assert_ok!(EthereumBeaconClient::submit_execution_header(
|
||||
RuntimeOrigin::signed(1),
|
||||
execution_header_update
|
||||
));
|
||||
|
||||
let header_root: H256 = TEST_HASH.into();
|
||||
<FinalizedBeaconState<Test>>::insert(
|
||||
header_root,
|
||||
CompactBeaconState {
|
||||
slot: far_ahead_finalized_header_slot,
|
||||
block_roots_root: Default::default(),
|
||||
},
|
||||
);
|
||||
LatestFinalizedBlockRoot::<Test>::set(header_root);
|
||||
|
||||
assert_err!(
|
||||
EthereumBeaconClient::submit(RuntimeOrigin::signed(1), next_update),
|
||||
Error::<Test>::ExecutionHeaderTooFarBehind
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn submit_irrelevant_update() {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
@@ -703,187 +580,6 @@ fn submit_update_with_invalid_sync_committee_update() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn submit_execution_header_update() {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
let finalized_header_update = Box::new(load_finalized_header_update_fixture());
|
||||
let execution_header_update = Box::new(load_execution_header_update_fixture());
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint));
|
||||
assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), finalized_header_update));
|
||||
assert_ok!(EthereumBeaconClient::submit_execution_header(
|
||||
RuntimeOrigin::signed(1),
|
||||
execution_header_update.clone()
|
||||
));
|
||||
assert!(<ExecutionHeaders<Test>>::contains_key(
|
||||
execution_header_update.execution_header.block_hash()
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn submit_execution_header_update_invalid_ancestry_proof() {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
let finalized_header_update = Box::new(load_finalized_header_update_fixture());
|
||||
let mut execution_header_update = Box::new(load_execution_header_update_fixture());
|
||||
if let Some(ref mut ancestry_proof) = execution_header_update.ancestry_proof {
|
||||
ancestry_proof.header_branch[0] = TEST_HASH.into()
|
||||
}
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint));
|
||||
assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), finalized_header_update));
|
||||
assert_err!(
|
||||
EthereumBeaconClient::submit_execution_header(
|
||||
RuntimeOrigin::signed(1),
|
||||
execution_header_update
|
||||
),
|
||||
Error::<Test>::InvalidAncestryMerkleProof
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn submit_execution_header_update_invalid_execution_header_proof() {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
let finalized_header_update = Box::new(load_finalized_header_update_fixture());
|
||||
let mut execution_header_update = Box::new(load_execution_header_update_fixture());
|
||||
execution_header_update.execution_branch[0] = TEST_HASH.into();
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint));
|
||||
assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), finalized_header_update));
|
||||
assert_err!(
|
||||
EthereumBeaconClient::submit_execution_header(
|
||||
RuntimeOrigin::signed(1),
|
||||
execution_header_update
|
||||
),
|
||||
Error::<Test>::InvalidExecutionHeaderProof
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn submit_execution_header_update_that_skips_block() {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
let finalized_header_update = Box::new(load_finalized_header_update_fixture());
|
||||
let execution_header_update = Box::new(load_execution_header_update_fixture());
|
||||
let mut skipped_block_execution_header_update =
|
||||
Box::new(load_execution_header_update_fixture());
|
||||
let mut skipped_execution_header =
|
||||
skipped_block_execution_header_update.execution_header.clone();
|
||||
|
||||
skipped_execution_header = match skipped_execution_header {
|
||||
VersionedExecutionPayloadHeader::Capella(execution_payload_header) => {
|
||||
let mut mut_execution_payload_header = execution_payload_header.clone();
|
||||
mut_execution_payload_header.block_number = execution_payload_header.block_number + 2;
|
||||
VersionedExecutionPayloadHeader::Capella(mut_execution_payload_header)
|
||||
},
|
||||
VersionedExecutionPayloadHeader::Deneb(execution_payload_header) => {
|
||||
let mut mut_execution_payload_header = execution_payload_header.clone();
|
||||
mut_execution_payload_header.block_number = execution_payload_header.block_number + 2;
|
||||
VersionedExecutionPayloadHeader::Deneb(mut_execution_payload_header)
|
||||
},
|
||||
};
|
||||
|
||||
skipped_block_execution_header_update.execution_header = skipped_execution_header;
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint));
|
||||
assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), finalized_header_update));
|
||||
assert_ok!(EthereumBeaconClient::submit_execution_header(
|
||||
RuntimeOrigin::signed(1),
|
||||
execution_header_update.clone()
|
||||
));
|
||||
assert!(<ExecutionHeaders<Test>>::contains_key(
|
||||
execution_header_update.execution_header.block_hash()
|
||||
));
|
||||
assert_err!(
|
||||
EthereumBeaconClient::submit_execution_header(
|
||||
RuntimeOrigin::signed(1),
|
||||
skipped_block_execution_header_update
|
||||
),
|
||||
Error::<Test>::ExecutionHeaderSkippedBlock
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn submit_execution_header_update_that_is_also_finalized_header_which_is_not_stored() {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
let finalized_header_update = Box::new(load_finalized_header_update_fixture());
|
||||
let mut execution_header_update = Box::new(load_execution_header_update_fixture());
|
||||
execution_header_update.ancestry_proof = None;
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint));
|
||||
assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), finalized_header_update));
|
||||
assert_err!(
|
||||
EthereumBeaconClient::submit_execution_header(
|
||||
RuntimeOrigin::signed(1),
|
||||
execution_header_update
|
||||
),
|
||||
Error::<Test>::ExpectedFinalizedHeaderNotStored
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn submit_execution_header_update_that_is_also_finalized_header_which_is_stored_but_slots_dont_match(
|
||||
) {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
let finalized_header_update = Box::new(load_finalized_header_update_fixture());
|
||||
let mut execution_header_update = Box::new(load_execution_header_update_fixture());
|
||||
execution_header_update.ancestry_proof = None;
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint));
|
||||
assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), finalized_header_update));
|
||||
|
||||
let block_root: H256 = execution_header_update.header.hash_tree_root().unwrap();
|
||||
|
||||
<FinalizedBeaconState<Test>>::insert(
|
||||
block_root,
|
||||
CompactBeaconState {
|
||||
slot: execution_header_update.header.slot + 1,
|
||||
block_roots_root: Default::default(),
|
||||
},
|
||||
);
|
||||
LatestFinalizedBlockRoot::<Test>::set(block_root);
|
||||
|
||||
assert_err!(
|
||||
EthereumBeaconClient::submit_execution_header(
|
||||
RuntimeOrigin::signed(1),
|
||||
execution_header_update
|
||||
),
|
||||
Error::<Test>::ExpectedFinalizedHeaderNotStored
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn submit_execution_header_not_finalized() {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
let finalized_header_update = Box::new(load_finalized_header_update_fixture());
|
||||
let update = Box::new(load_execution_header_update_fixture());
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint));
|
||||
assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), finalized_header_update));
|
||||
|
||||
<FinalizedBeaconState<Test>>::mutate(<LatestFinalizedBlockRoot<Test>>::get(), |x| {
|
||||
let prev = x.unwrap();
|
||||
*x = Some(CompactBeaconState { slot: update.header.slot - 1, ..prev });
|
||||
});
|
||||
|
||||
assert_err!(
|
||||
EthereumBeaconClient::submit_execution_header(RuntimeOrigin::signed(1), update),
|
||||
Error::<Test>::HeaderNotFinalized
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Check that a gap of more than 8192 slots between finalized headers is not allowed.
|
||||
#[test]
|
||||
fn submit_finalized_header_update_with_too_large_gap() {
|
||||
@@ -943,37 +639,21 @@ fn submit_finalized_header_update_with_gap_at_limit() {
|
||||
|
||||
#[test]
|
||||
fn verify_message() {
|
||||
let header = get_message_verification_header();
|
||||
let (event_log, proof) = get_message_verification_payload();
|
||||
let block_hash = proof.block_hash;
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
<ExecutionHeaderBuffer<Test>>::insert(block_hash, header);
|
||||
assert_ok!(initialize_storage());
|
||||
assert_ok!(EthereumBeaconClient::verify(&event_log, &proof));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_message_missing_header() {
|
||||
let (event_log, proof) = get_message_verification_payload();
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
assert_err!(
|
||||
EthereumBeaconClient::verify(&event_log, &proof),
|
||||
VerificationError::HeaderNotFound
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_message_invalid_proof() {
|
||||
let header = get_message_verification_header();
|
||||
let (event_log, mut proof) = get_message_verification_payload();
|
||||
proof.data.1[0] = TEST_HASH.into();
|
||||
let block_hash = proof.block_hash;
|
||||
proof.receipt_proof.1[0] = TEST_HASH.into();
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
<ExecutionHeaderBuffer<Test>>::insert(block_hash, header);
|
||||
assert_ok!(initialize_storage());
|
||||
assert_err!(
|
||||
EthereumBeaconClient::verify(&event_log, &proof),
|
||||
VerificationError::InvalidProof
|
||||
@@ -983,29 +663,28 @@ fn verify_message_invalid_proof() {
|
||||
|
||||
#[test]
|
||||
fn verify_message_invalid_receipts_root() {
|
||||
let mut header = get_message_verification_header();
|
||||
let (event_log, proof) = get_message_verification_payload();
|
||||
let block_hash = proof.block_hash;
|
||||
header.receipts_root = TEST_HASH.into();
|
||||
let (event_log, mut proof) = get_message_verification_payload();
|
||||
let mut payload = deneb::ExecutionPayloadHeader::default();
|
||||
payload.receipts_root = TEST_HASH.into();
|
||||
proof.execution_proof.execution_header = VersionedExecutionPayloadHeader::Deneb(payload);
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
<ExecutionHeaderBuffer<Test>>::insert(block_hash, header);
|
||||
assert_ok!(initialize_storage());
|
||||
assert_err!(
|
||||
EthereumBeaconClient::verify(&event_log, &proof),
|
||||
VerificationError::InvalidProof
|
||||
VerificationError::InvalidExecutionProof(
|
||||
Error::<Test>::BlockBodyHashTreeRootFailed.into()
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_message_invalid_log() {
|
||||
let header = get_message_verification_header();
|
||||
let (mut event_log, proof) = get_message_verification_payload();
|
||||
let block_hash = proof.block_hash;
|
||||
event_log.topics = vec![H256::zero(); 10];
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
<ExecutionHeaderBuffer<Test>>::insert(block_hash, header);
|
||||
assert_ok!(initialize_storage());
|
||||
assert_err!(
|
||||
EthereumBeaconClient::verify(&event_log, &proof),
|
||||
VerificationError::InvalidLog
|
||||
@@ -1015,13 +694,11 @@ fn verify_message_invalid_log() {
|
||||
|
||||
#[test]
|
||||
fn verify_message_receipt_does_not_contain_log() {
|
||||
let header = get_message_verification_header();
|
||||
let (mut event_log, proof) = get_message_verification_payload();
|
||||
let block_hash = proof.block_hash;
|
||||
event_log.data = hex!("f9013c94ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0f863a01b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ada000000000000000000000000000000000000000000000000000000000000003e8a00000000000000000000000000000000000000000000000000000000000000002b8c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000068000f000000000000000101d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec70100000101001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c0000e8890423c78a0000000000000000000000000000000000000000000000000000000000000000").to_vec();
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
<ExecutionHeaderBuffer<Test>>::insert(block_hash, header);
|
||||
assert_ok!(initialize_storage());
|
||||
assert_err!(
|
||||
EthereumBeaconClient::verify(&event_log, &proof),
|
||||
VerificationError::LogNotFound
|
||||
@@ -1033,7 +710,6 @@ fn verify_message_receipt_does_not_contain_log() {
|
||||
fn set_operating_mode() {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
let update = Box::new(load_finalized_header_update_fixture());
|
||||
let execution_header_update = Box::new(load_execution_header_update_fixture());
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint));
|
||||
@@ -1047,14 +723,6 @@ fn set_operating_mode() {
|
||||
EthereumBeaconClient::submit(RuntimeOrigin::signed(1), update),
|
||||
Error::<Test>::Halted
|
||||
);
|
||||
|
||||
assert_noop!(
|
||||
EthereumBeaconClient::submit_execution_header(
|
||||
RuntimeOrigin::signed(1),
|
||||
execution_header_update
|
||||
),
|
||||
Error::<Test>::Halted
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1070,3 +738,107 @@ fn set_operating_mode_root_only() {
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_execution_proof_invalid_ancestry_proof() {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
let finalized_header_update = Box::new(load_finalized_header_update_fixture());
|
||||
let mut execution_header_update = Box::new(load_execution_proof_fixture());
|
||||
if let Some(ref mut ancestry_proof) = execution_header_update.ancestry_proof {
|
||||
ancestry_proof.header_branch[0] = TEST_HASH.into()
|
||||
}
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint));
|
||||
assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), finalized_header_update));
|
||||
assert_err!(
|
||||
EthereumBeaconClient::verify_execution_proof(&execution_header_update),
|
||||
Error::<Test>::InvalidAncestryMerkleProof
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_execution_proof_invalid_execution_header_proof() {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
let finalized_header_update = Box::new(load_finalized_header_update_fixture());
|
||||
let mut execution_header_update = Box::new(load_execution_proof_fixture());
|
||||
execution_header_update.execution_branch[0] = TEST_HASH.into();
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint));
|
||||
assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), finalized_header_update));
|
||||
assert_err!(
|
||||
EthereumBeaconClient::verify_execution_proof(&execution_header_update),
|
||||
Error::<Test>::InvalidExecutionHeaderProof
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_execution_proof_that_is_also_finalized_header_which_is_not_stored() {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
let finalized_header_update = Box::new(load_finalized_header_update_fixture());
|
||||
let mut execution_header_update = Box::new(load_execution_proof_fixture());
|
||||
execution_header_update.ancestry_proof = None;
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint));
|
||||
assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), finalized_header_update));
|
||||
assert_err!(
|
||||
EthereumBeaconClient::verify_execution_proof(&execution_header_update),
|
||||
Error::<Test>::ExpectedFinalizedHeaderNotStored
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn submit_execution_proof_that_is_also_finalized_header_which_is_stored_but_slots_dont_match() {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
let finalized_header_update = Box::new(load_finalized_header_update_fixture());
|
||||
let mut execution_header_update = Box::new(load_execution_proof_fixture());
|
||||
execution_header_update.ancestry_proof = None;
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint));
|
||||
assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), finalized_header_update));
|
||||
|
||||
let block_root: H256 = execution_header_update.header.hash_tree_root().unwrap();
|
||||
|
||||
<FinalizedBeaconState<Test>>::insert(
|
||||
block_root,
|
||||
CompactBeaconState {
|
||||
slot: execution_header_update.header.slot + 1,
|
||||
block_roots_root: Default::default(),
|
||||
},
|
||||
);
|
||||
LatestFinalizedBlockRoot::<Test>::set(block_root);
|
||||
|
||||
assert_err!(
|
||||
EthereumBeaconClient::verify_execution_proof(&execution_header_update),
|
||||
Error::<Test>::ExpectedFinalizedHeaderNotStored
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_execution_proof_not_finalized() {
|
||||
let checkpoint = Box::new(load_checkpoint_update_fixture());
|
||||
let finalized_header_update = Box::new(load_finalized_header_update_fixture());
|
||||
let update = Box::new(load_execution_proof_fixture());
|
||||
|
||||
new_tester().execute_with(|| {
|
||||
assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint));
|
||||
assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), finalized_header_update));
|
||||
|
||||
<FinalizedBeaconState<Test>>::mutate(<LatestFinalizedBlockRoot<Test>>::get(), |x| {
|
||||
let prev = x.unwrap();
|
||||
*x = Some(CompactBeaconState { slot: update.header.slot - 1, ..prev });
|
||||
});
|
||||
|
||||
assert_err!(
|
||||
EthereumBeaconClient::verify_execution_proof(&update),
|
||||
Error::<Test>::HeaderNotFinalized
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -15,17 +15,7 @@ pub type CheckpointUpdate = primitives::CheckpointUpdate<SC_SIZE>;
|
||||
pub type Update = primitives::Update<SC_SIZE, SC_BITS_SIZE>;
|
||||
pub type NextSyncCommitteeUpdate = primitives::NextSyncCommitteeUpdate<SC_SIZE>;
|
||||
|
||||
pub use primitives::ExecutionHeaderUpdate;
|
||||
|
||||
/// ExecutionHeader ring buffer implementation
|
||||
pub type ExecutionHeaderBuffer<T> = RingBufferMapImpl<
|
||||
u32,
|
||||
<T as crate::Config>::MaxExecutionHeadersToKeep,
|
||||
crate::ExecutionHeaderIndex<T>,
|
||||
crate::ExecutionHeaderMapping<T>,
|
||||
crate::ExecutionHeaders<T>,
|
||||
OptionQuery,
|
||||
>;
|
||||
pub use primitives::{AncestryProof, ExecutionProof};
|
||||
|
||||
/// FinalizedState ring buffer implementation
|
||||
pub(crate) type FinalizedBeaconStateBuffer<T> = RingBufferMapImpl<
|
||||
|
||||
@@ -36,7 +36,6 @@ pub trait WeightInfo {
|
||||
fn force_checkpoint() -> Weight;
|
||||
fn submit() -> Weight;
|
||||
fn submit_with_sync_committee() -> Weight;
|
||||
fn submit_execution_header() -> Weight;
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests
|
||||
@@ -59,10 +58,4 @@ impl WeightInfo for () {
|
||||
.saturating_add(RocksDbWeight::get().reads(6))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
}
|
||||
fn submit_execution_header() -> Weight {
|
||||
Weight::from_parts(113_158_000_u64, 0)
|
||||
.saturating_add(Weight::from_parts(0, 3537))
|
||||
.saturating_add(RocksDbWeight::get().reads(5))
|
||||
.saturating_add(RocksDbWeight::get().writes(4))
|
||||
}
|
||||
}
|
||||
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
{
|
||||
"header": {
|
||||
"slot": 215,
|
||||
"proposer_index": 2,
|
||||
"parent_root": "0x97518f531a252bb6ca547b21aca9da767943ec99211d3b15c804e34c3a523f45",
|
||||
"state_root": "0xb088b5a3a8c90d6dc919a695cd7bb0267c6f983ea2e675c559ceb8f46cb90b67",
|
||||
"body_root": "0x0ba23c8224fdd01531d5ad51486353bd524a0b4c20bca704e26d3210616f829b"
|
||||
},
|
||||
"ancestry_proof": {
|
||||
"header_branch": [
|
||||
"0x97518f531a252bb6ca547b21aca9da767943ec99211d3b15c804e34c3a523f45",
|
||||
"0x5ce0db996bd499c2b4f7a93263d5aafd052f420efb617cce6fdd54e25516aa45",
|
||||
"0x84f0e373b66011ce774c7061440c0a50a51cce2b4b335395eee3e563d605597f",
|
||||
"0x48f9ccc5f9594142c18c3b5c39a99f0549329c6ab3ba06c9a50030eadca87770",
|
||||
"0xf89d6e311e05bc75a6f63ce118bccce254551f1a88d54c3b4f773f81f946bd99",
|
||||
"0x2edd6d893c22636675147c07dfcdb541a146e87c3f15b51c388be4868246dc9b",
|
||||
"0xd76b7de5f856e3208a91a42c9c398a7f4fab35e667bf916346050ae742514a2d",
|
||||
"0x83a2e233e76385953ca41de4c3afe60471a61f0cc1b3846b4a0670e3e563b747",
|
||||
"0xe783a5a109c2ad74e4eb53e8f6b11b31266a92a9e16c1fd5873109c5d41b282c",
|
||||
"0xd4ea1ef3869ee6a0fd0b19d7d70027d144eecd4f1d32cbf47632a0a9069164b9",
|
||||
"0xf8179564b58eb93a850d35e4156a04db651106442ad891c3e85155c1762792f1",
|
||||
"0x4cbb1edb48cf1e32fb30db60aaaeaf6190ffe4d0c8dbc96cec307daecb78be12",
|
||||
"0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f"
|
||||
],
|
||||
"finalized_block_root": "0x890a7f23b9ed2160901654be9efc575d6830ca860e2a97866ae3423fb7bd7231"
|
||||
},
|
||||
"execution_header": {
|
||||
"Deneb": {
|
||||
"parent_hash": "0xd82ec63f5c5e6ba61d62f09c188f158e6449b94bdcc31941e68639eec3c4cf7a",
|
||||
"fee_recipient": "0x0000000000000000000000000000000000000000",
|
||||
"state_root": "0x8b65545fe5f3216b47b6339b9c91ca2b7f1032a970b04246d9e9fb4460ee34c3",
|
||||
"receipts_root": "0x7b1f61b9714c080ef0be014e01657a15f45f0304b477beebc7ca5596c8033095",
|
||||
"logs_bloom": "0x00000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000080000000000000000000000000000004000000000080000000000000000000000000000000000010100000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000040004000000000000002000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000200000000000010",
|
||||
"prev_randao": "0x6d9e2a012d82b1b6cb0a2c1c1ed24cc16dbb56e6e39ae545371e0666ab057862",
|
||||
"block_number": 215,
|
||||
"gas_limit": 64842908,
|
||||
"gas_used": 119301,
|
||||
"timestamp": 1705859527,
|
||||
"extra_data": "0xd983010d0a846765746888676f312e32312e358664617277696e",
|
||||
"base_fee_per_gas": 7,
|
||||
"block_hash": "0x48498dbfbcfae53a7f4c289ee00747aceea925f6260c50ead5a33e1c55c40f98",
|
||||
"transactions_root": "0x5ebc1347fe3df0611d4f66b19bd8e1c6f4eaed0371d850f14c83b1c77ea234e6",
|
||||
"withdrawals_root": "0x792930bbd5baac43bcc798ee49aa8185ef76bb3b44ba62b91d86ae569e4bb535",
|
||||
"blob_gas_used": 0,
|
||||
"excess_blob_gas": 0
|
||||
}
|
||||
},
|
||||
"execution_branch": [
|
||||
"0xf8c69d3830406d668619bcccc13c8dddde41e863326f7418b241d5924c4ad34a",
|
||||
"0xb46f0c01805fe212e15907981b757e6c496b0cb06664224655613dcec82505bb",
|
||||
"0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71",
|
||||
"0xf4d6b5cf9c6e212615c3674fa625d04eb1114153fb221ef5ad02aa433fc67cfb"
|
||||
]
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"header": {
|
||||
"slot": 393,
|
||||
"proposer_index": 4,
|
||||
"parent_root": "0x6545b47a614a1dd4cad042a0cdbbf5be347e8ffcdc02c6c64540d5153acebeef",
|
||||
"state_root": "0xb62ac34a8cb82497be9542fe2114410c9f6021855b766015406101a1f3d86434",
|
||||
"body_root": "0x04005fe231e11a5b7b1580cb73b177ae8b338bedd745497e6bb7122126a806db"
|
||||
},
|
||||
"ancestry_proof": {
|
||||
"header_branch": [
|
||||
"0x6545b47a614a1dd4cad042a0cdbbf5be347e8ffcdc02c6c64540d5153acebeef",
|
||||
"0xfa84cc88ca53a72181599ff4eb07d8b444bce023fe2347c3b4f51004c43439d3",
|
||||
"0xcadc8ae211c6f2221c9138e829249adf902419c78eb4727a150baa4d9a02cc9d",
|
||||
"0x33a89962df08a35c52bd7e1d887cd71fa7803e68787d05c714036f6edf75947c",
|
||||
"0x2c9760fce5c2829ef3f25595a703c21eb22d0186ce223295556ed5da663a82cf",
|
||||
"0xe1aa87654db79c8a0ecd6c89726bb662fcb1684badaef5cd5256f479e3c622e1",
|
||||
"0xaa70d5f314e4a1fbb9c362f3db79b21bf68b328887248651fbd29fc501d0ca97",
|
||||
"0x160b6c235b3a1ed4ef5f80b03ee1c76f7bf3f591c92fca9d8663e9221b9f9f0f",
|
||||
"0xf68d7dcd6a07a18e9de7b5d2aa1980eb962e11d7dcb584c96e81a7635c8d2535",
|
||||
"0x1d5f912dfd6697110dd1ecb5cb8e77952eef57d85deb373572572df62bb157fc",
|
||||
"0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b",
|
||||
"0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220",
|
||||
"0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f"
|
||||
],
|
||||
"finalized_block_root": "0x751414cd97c0624f922b3e80285e9f776b08fa22fd5f87391f2ed7ef571a8d46"
|
||||
},
|
||||
"execution_header": {
|
||||
"Deneb": {
|
||||
"parent_hash": "0x8092290aa21b7751576440f77edd02a94058429ce50e63a92d620951fb25eda2",
|
||||
"fee_recipient": "0x0000000000000000000000000000000000000000",
|
||||
"state_root": "0x96a83e9ddf745346fafcb0b03d57314623df669ed543c110662b21302a0fae8b",
|
||||
"receipts_root": "0xdccdfceea05036f7b61dcdabadc937945d31e68a8d3dfd4dc85684457988c284",
|
||||
"logs_bloom": "0x00000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000080000000400000000000000000000004000000000080000000000000000000000000000000000010100000000000000000000000000000000020000000000000000000000000000000000080000000000000000000000000000040004000000000000002002002000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000200000200000010",
|
||||
"prev_randao": "0x62e309d4f5119d1f5c783abc20fc1a549efbab546d8d0b25ff1cfd58be524e67",
|
||||
"block_number": 393,
|
||||
"gas_limit": 54492273,
|
||||
"gas_used": 199644,
|
||||
"timestamp": 1710552813,
|
||||
"extra_data": "0xd983010d0b846765746888676f312e32312e368664617277696e",
|
||||
"base_fee_per_gas": 7,
|
||||
"block_hash": "0x6a9810efb9581d30c1a5c9074f27c68ea779a8c1ae31c213241df16225f4e131",
|
||||
"transactions_root": "0x2cfa6ed7327e8807c7973516c5c32a68ef2459e586e8067e113d081c3bd8c07d",
|
||||
"withdrawals_root": "0x792930bbd5baac43bcc798ee49aa8185ef76bb3b44ba62b91d86ae569e4bb535",
|
||||
"blob_gas_used": 0,
|
||||
"excess_blob_gas": 0
|
||||
}
|
||||
},
|
||||
"execution_branch": [
|
||||
"0xa6833fa629f3286b6916c6e50b8bf089fc9126bee6f64d0413b4e59c1265834d",
|
||||
"0xb46f0c01805fe212e15907981b757e6c496b0cb06664224655613dcec82505bb",
|
||||
"0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71",
|
||||
"0xd3af7c05c516726be7505239e0b9c7cb53d24abce6b91cdb3b3995f0164a75da"
|
||||
]
|
||||
}
|
||||
+25
-23
@@ -1,38 +1,40 @@
|
||||
{
|
||||
"attested_header": {
|
||||
"slot": 2566,
|
||||
"proposer_index": 6,
|
||||
"parent_root": "0x6eb9f13a2c496318ce1ab3087bbd872f5c9519a1a7ca8231a2453e3cb523af00",
|
||||
"state_root": "0xc8cb12766113dff7e46d2917267bf33d0626d99dd47715fcdbc5c65fad3c04b4",
|
||||
"body_root": "0xd8cfd0d7bc9bc3724417a1655bb0a67c0765ca36197320f4d834150b52ef1420"
|
||||
"slot": 933,
|
||||
"proposer_index": 1,
|
||||
"parent_root": "0xf5fc63e2780ca302b97aea73fc95d74d702b5afe9a772c2b68f695026337b620",
|
||||
"state_root": "0xd856d11636bc4d866e78be9e747b222b0977556a367ab42e4085277301438050",
|
||||
"body_root": "0x5689091ab4eb76c2e876271add4924e1c66ce987c300c24aac2ad8c703e9a33f"
|
||||
},
|
||||
"sync_aggregate": {
|
||||
"sync_committee_bits": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"sync_committee_signature": "0x9296f9a0387f2cac47008e22ad7c3cd3d49d35384c13e6aa1eacca7dca7c3d2ca81515e50eb3396b9550ed20ef7d8fa2049a186598feb2c00e93728045fcff917733d1827481b8fc95f3913e27fc70112c2490496eb57bb7181f02c3f9fd471f"
|
||||
"sync_committee_signature": "0x93a3d482fe2a2f7fd2b634169752a8fddf1dc28b23a020b398be8526faf37a74ca0f6db1bed78a9c7256c09a6115235e108e0e8a7ce09287317b0856c4b77dfa5adba6cf4c3ebea5bfa4cd2fcde80fd0a532f2defe65d530201d5d2258796559"
|
||||
},
|
||||
"signature_slot": 2567,
|
||||
"signature_slot": 934,
|
||||
"next_sync_committee_update": null,
|
||||
"finalized_header": {
|
||||
"slot": 2496,
|
||||
"proposer_index": 2,
|
||||
"parent_root": "0xc99e49787106733eeebab4d93eb326e1f2214575c9d928f0c4ab0da0776f1622",
|
||||
"state_root": "0xfbf8a08c86ef36bd173e37e733da4a78aa8e85fee99a990e858dd12a59087fde",
|
||||
"body_root": "0xa2a8ad06901447b2807a9059580a4c40d8a941f325b1343c69f7c7c6c90e4ab0"
|
||||
"slot": 864,
|
||||
"proposer_index": 4,
|
||||
"parent_root": "0x614e7672f991ac268cd841055973f55e1e42228831a211adef207bb7329be614",
|
||||
"state_root": "0x5fa8dfca3d760e4242ab46d529144627aa85348a19173b6e081172c701197a4a",
|
||||
"body_root": "0x0f34c083b1803666bb1ac5e73fa71582731a2cf37d279ff0a3b0cad5a2ff371e"
|
||||
},
|
||||
"finality_branch": [
|
||||
"0x4e00000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x1b00000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x10c726fac935bf9657cc7476d3cfa7bedec5983dcfb59e8a7df6d0a619e108d7",
|
||||
"0x98e9116c6bb7f20de18800dc63e73e689d06d6a47d35b5e2b32cf093d475840d",
|
||||
"0x958b8e43347f6df6fa5eb3d62d06a862381a6585aa40640dd1c0de11f1cf89c1",
|
||||
"0xf107dce04faa86a28fc5d4a618be9cb8d4fc3c23d6c42c3624f3ff4bf6586a03",
|
||||
"0xa501cdc02e86969ac3e4d0c5a36f4f049efaa1ab8cb6693f51d130eb52a80f30"
|
||||
"0xf12d9aededc72724e417b518fe6f847684f26f81616243dedf8c551cc7d504f5",
|
||||
"0x89a85d0907ab3fd6e00ae385f61d456c6191646404ae7b8d23d0e60440cf4d00",
|
||||
"0x9fc943b6020eb61d780d78bcc6f6102a81d2c868d58f36e61c6e286a2dc4d8c2"
|
||||
],
|
||||
"block_roots_root": "0xd160b7687041891b73e54b06fc4e04f82d0fa8fdd76705895e216c6b24709dfe",
|
||||
"block_roots_root": "0xb9aab9c388c4e4fcd899b71f62c498fc73406e38e8eb14aa440e9affa06f2a10",
|
||||
"block_roots_branch": [
|
||||
"0x105290e42d98ab6a0ada6e55453cede36c672abf645eeb986b88d7487616e135",
|
||||
"0x9da41f274bcdf6122335443d9ce94d07163b48dba3e2f9499ff56f4e48b48b99",
|
||||
"0xecea7e1d3152d8130e83afdfe34b4de4ba2b69a33c9471991096daf454de9cf5",
|
||||
"0xb2bf1758e50b2bfff29169fbc70fdb884b2b05bb615dbc53567574da6f4f1ae2",
|
||||
"0xcd87069daf70975779126d6af833b7d636c75ca4d5e750ebcad0e76408a5e5bf"
|
||||
]
|
||||
"0x733422bd810895dab74cbbe07c69dd440cbb51f573181ad4dddac30fcdd0f41f",
|
||||
"0x9b9eca73ab01d14549c325ba1b4610bb20bf1f8ec2dbd649f9d8cc7f3cea75fa",
|
||||
"0xbcc666ad0ad9f9725cbd682bc95589d35b1b53b2a615f1e6e8dd5e086336becf",
|
||||
"0x3069b547a08f703a1715016e926cbd64e71f93f64fb68d98d8c8f1ab745c46e5",
|
||||
"0xc2de7e1097239404e17b263cfa0473533cc41e903cb03440d633bc5c27314cb4"
|
||||
],
|
||||
"execution_header": null,
|
||||
"execution_branch": null
|
||||
}
|
||||
+71
-23
@@ -1,31 +1,79 @@
|
||||
{
|
||||
"execution_header": {
|
||||
"parent_hash": "0xd82ec63f5c5e6ba61d62f09c188f158e6449b94bdcc31941e68639eec3c4cf7a",
|
||||
"state_root": "0x8b65545fe5f3216b47b6339b9c91ca2b7f1032a970b04246d9e9fb4460ee34c3",
|
||||
"receipts_root": "0x7b1f61b9714c080ef0be014e01657a15f45f0304b477beebc7ca5596c8033095",
|
||||
"block_number": 215
|
||||
"event_log": {
|
||||
"address": "0xeda338e4dc46038493b885327842fd3e301cab39",
|
||||
"topics": [
|
||||
"0x7153f9357c8ea496bba60bf82e67143e27b64462b49041f8e689e1b05728f84f",
|
||||
"0xc173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539",
|
||||
"0x5f7060e971b0dc81e63f0aa41831091847d97c1a4693ac450cc128c7214e65e0"
|
||||
],
|
||||
"data": "0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002e00a736aa00000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d00e40b54020000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"message": {
|
||||
"event_log": {
|
||||
"address": "0xeda338e4dc46038493b885327842fd3e301cab39",
|
||||
"topics": [
|
||||
"0x7153f9357c8ea496bba60bf82e67143e27b64462b49041f8e689e1b05728f84f",
|
||||
"0xc173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539",
|
||||
"0x5f7060e971b0dc81e63f0aa41831091847d97c1a4693ac450cc128c7214e65e0"
|
||||
"proof": {
|
||||
"block_hash": "0x6a9810efb9581d30c1a5c9074f27c68ea779a8c1ae31c213241df16225f4e131",
|
||||
"tx_index": 0,
|
||||
"receipt_proof": {
|
||||
"keys": [
|
||||
"0xdccdfceea05036f7b61dcdabadc937945d31e68a8d3dfd4dc85684457988c284",
|
||||
"0x4a98e45a319168b0fc6005ce6b744ee9bf54338e2c0784b976a8578d241ced0f"
|
||||
],
|
||||
"data": "0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002e00a736aa00000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d00e40b54020000000000000000000000000000000000000000000000000000000000"
|
||||
"values": [
|
||||
"0xf851a09c01dd6d2d8de951c45af23d3ad00829ce021c04d6c8acbe1612d456ee320d4980808080808080a04a98e45a319168b0fc6005ce6b744ee9bf54338e2c0784b976a8578d241ced0f8080808080808080",
|
||||
"0xf9028c30b9028802f90284018301d205b9010000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000080000000000000000000000000000004000000000080000000000000000000000000000000000010100000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000040004000000000000002000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000200000000000010f90179f85894eda338e4dc46038493b885327842fd3e301cab39e1a0f78bb28d4b1d7da699e5c0bc2be29c2b04b5aab6aacf6298fe5304f9db9c6d7ea000000000000000000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7df9011c94eda338e4dc46038493b885327842fd3e301cab39f863a07153f9357c8ea496bba60bf82e67143e27b64462b49041f8e689e1b05728f84fa0c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539a05f7060e971b0dc81e63f0aa41831091847d97c1a4693ac450cc128c7214e65e0b8a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002e00a736aa00000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d00e40b54020000000000000000000000000000000000000000000000000000000000"
|
||||
]
|
||||
},
|
||||
"Proof": {
|
||||
"block_hash": "0x48498dbfbcfae53a7f4c289ee00747aceea925f6260c50ead5a33e1c55c40f98",
|
||||
"tx_index": 0,
|
||||
"data": {
|
||||
"keys": [
|
||||
"0x7b1f61b9714c080ef0be014e01657a15f45f0304b477beebc7ca5596c8033095"
|
||||
"execution_proof": {
|
||||
"header": {
|
||||
"slot": 393,
|
||||
"proposer_index": 4,
|
||||
"parent_root": "0x6545b47a614a1dd4cad042a0cdbbf5be347e8ffcdc02c6c64540d5153acebeef",
|
||||
"state_root": "0xb62ac34a8cb82497be9542fe2114410c9f6021855b766015406101a1f3d86434",
|
||||
"body_root": "0x04005fe231e11a5b7b1580cb73b177ae8b338bedd745497e6bb7122126a806db"
|
||||
},
|
||||
"ancestry_proof": {
|
||||
"header_branch": [
|
||||
"0x6545b47a614a1dd4cad042a0cdbbf5be347e8ffcdc02c6c64540d5153acebeef",
|
||||
"0xfa84cc88ca53a72181599ff4eb07d8b444bce023fe2347c3b4f51004c43439d3",
|
||||
"0xcadc8ae211c6f2221c9138e829249adf902419c78eb4727a150baa4d9a02cc9d",
|
||||
"0x33a89962df08a35c52bd7e1d887cd71fa7803e68787d05c714036f6edf75947c",
|
||||
"0x2c9760fce5c2829ef3f25595a703c21eb22d0186ce223295556ed5da663a82cf",
|
||||
"0xe1aa87654db79c8a0ecd6c89726bb662fcb1684badaef5cd5256f479e3c622e1",
|
||||
"0xaa70d5f314e4a1fbb9c362f3db79b21bf68b328887248651fbd29fc501d0ca97",
|
||||
"0x160b6c235b3a1ed4ef5f80b03ee1c76f7bf3f591c92fca9d8663e9221b9f9f0f",
|
||||
"0xf68d7dcd6a07a18e9de7b5d2aa1980eb962e11d7dcb584c96e81a7635c8d2535",
|
||||
"0x1d5f912dfd6697110dd1ecb5cb8e77952eef57d85deb373572572df62bb157fc",
|
||||
"0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b",
|
||||
"0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220",
|
||||
"0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f"
|
||||
],
|
||||
"values": [
|
||||
"0xf9028e822080b9028802f90284018301d205b9010000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000080000000000000000000000000000004000000000080000000000000000000000000000000000010100000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000040004000000000000002000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000200000000000010f90179f85894eda338e4dc46038493b885327842fd3e301cab39e1a0f78bb28d4b1d7da699e5c0bc2be29c2b04b5aab6aacf6298fe5304f9db9c6d7ea000000000000000000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7df9011c94eda338e4dc46038493b885327842fd3e301cab39f863a07153f9357c8ea496bba60bf82e67143e27b64462b49041f8e689e1b05728f84fa0c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539a05f7060e971b0dc81e63f0aa41831091847d97c1a4693ac450cc128c7214e65e0b8a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002e00a736aa00000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d00e40b54020000000000000000000000000000000000000000000000000000000000"
|
||||
]
|
||||
}
|
||||
"finalized_block_root": "0x751414cd97c0624f922b3e80285e9f776b08fa22fd5f87391f2ed7ef571a8d46"
|
||||
},
|
||||
"execution_header": {
|
||||
"Deneb": {
|
||||
"parent_hash": "0x8092290aa21b7751576440f77edd02a94058429ce50e63a92d620951fb25eda2",
|
||||
"fee_recipient": "0x0000000000000000000000000000000000000000",
|
||||
"state_root": "0x96a83e9ddf745346fafcb0b03d57314623df669ed543c110662b21302a0fae8b",
|
||||
"receipts_root": "0xdccdfceea05036f7b61dcdabadc937945d31e68a8d3dfd4dc85684457988c284",
|
||||
"logs_bloom": "0x00000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000080000000400000000000000000000004000000000080000000000000000000000000000000000010100000000000000000000000000000000020000000000000000000000000000000000080000000000000000000000000000040004000000000000002002002000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000200000200000010",
|
||||
"prev_randao": "0x62e309d4f5119d1f5c783abc20fc1a549efbab546d8d0b25ff1cfd58be524e67",
|
||||
"block_number": 393,
|
||||
"gas_limit": 54492273,
|
||||
"gas_used": 199644,
|
||||
"timestamp": 1710552813,
|
||||
"extra_data": "0xd983010d0b846765746888676f312e32312e368664617277696e",
|
||||
"base_fee_per_gas": 7,
|
||||
"block_hash": "0x6a9810efb9581d30c1a5c9074f27c68ea779a8c1ae31c213241df16225f4e131",
|
||||
"transactions_root": "0x2cfa6ed7327e8807c7973516c5c32a68ef2459e586e8067e113d081c3bd8c07d",
|
||||
"withdrawals_root": "0x792930bbd5baac43bcc798ee49aa8185ef76bb3b44ba62b91d86ae569e4bb535",
|
||||
"blob_gas_used": 0,
|
||||
"excess_blob_gas": 0
|
||||
}
|
||||
},
|
||||
"execution_branch": [
|
||||
"0xa6833fa629f3286b6916c6e50b8bf089fc9126bee6f64d0413b4e59c1265834d",
|
||||
"0xb46f0c01805fe212e15907981b757e6c496b0cb06664224655613dcec82505bb",
|
||||
"0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71",
|
||||
"0xd3af7c05c516726be7505239e0b9c7cb53d24abce6b91cdb3b3995f0164a75da"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-15
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"header": {
|
||||
"slot": 2496,
|
||||
"proposer_index": 2,
|
||||
"parent_root": "0xc99e49787106733eeebab4d93eb326e1f2214575c9d928f0c4ab0da0776f1622",
|
||||
"state_root": "0xfbf8a08c86ef36bd173e37e733da4a78aa8e85fee99a990e858dd12a59087fde",
|
||||
"body_root": "0xa2a8ad06901447b2807a9059580a4c40d8a941f325b1343c69f7c7c6c90e4ab0"
|
||||
"slot": 864,
|
||||
"proposer_index": 4,
|
||||
"parent_root": "0x614e7672f991ac268cd841055973f55e1e42228831a211adef207bb7329be614",
|
||||
"state_root": "0x5fa8dfca3d760e4242ab46d529144627aa85348a19173b6e081172c701197a4a",
|
||||
"body_root": "0x0f34c083b1803666bb1ac5e73fa71582731a2cf37d279ff0a3b0cad5a2ff371e"
|
||||
},
|
||||
"current_sync_committee": {
|
||||
"pubkeys": [
|
||||
@@ -525,18 +525,18 @@
|
||||
},
|
||||
"current_sync_committee_branch": [
|
||||
"0x3ade38d498a062b50880a9409e1ca3a7fd4315d91eeb3bb83e56ac6bfe8d6a59",
|
||||
"0x93880225bf99a0c5ec22b266ff829837754e9c5edf37a68c05b8f803fd82fa45",
|
||||
"0x4c60656ec9a95fcf11030ad309c716b5b15beb7f60a0bcfc7c9d4eff505472ff",
|
||||
"0x22d1645fceb4bf9a695043dda19a53e784ec70df6a6b1bd66ea30eba1cca5f2f",
|
||||
"0xa8fc6cad84ceefc633ec56c2d031d525e1cb4b51c70eb252919fce5bba9a1fde"
|
||||
"0xa9e90f89e7f90fd5d79a6bbcaf40ba5cfc05ab1b561ac51c84867c32248d5b1e",
|
||||
"0xbd1a76b03e02402bb24a627de1980a80ab17691980271f597b844b89b497ef75",
|
||||
"0x07bbcd27c7cad089023db046eda17e8209842b7d97add8b873519e84fe6480e7",
|
||||
"0x94c11eeee4cb6192bf40810f23486d8c75dfbc2b6f28d988d6f74435ede243b0"
|
||||
],
|
||||
"validators_root": "0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69",
|
||||
"block_roots_root": "0xd160b7687041891b73e54b06fc4e04f82d0fa8fdd76705895e216c6b24709dfe",
|
||||
"block_roots_root": "0xb9aab9c388c4e4fcd899b71f62c498fc73406e38e8eb14aa440e9affa06f2a10",
|
||||
"block_roots_branch": [
|
||||
"0x105290e42d98ab6a0ada6e55453cede36c672abf645eeb986b88d7487616e135",
|
||||
"0x9da41f274bcdf6122335443d9ce94d07163b48dba3e2f9499ff56f4e48b48b99",
|
||||
"0xecea7e1d3152d8130e83afdfe34b4de4ba2b69a33c9471991096daf454de9cf5",
|
||||
"0xb2bf1758e50b2bfff29169fbc70fdb884b2b05bb615dbc53567574da6f4f1ae2",
|
||||
"0xcd87069daf70975779126d6af833b7d636c75ca4d5e750ebcad0e76408a5e5bf"
|
||||
"0x733422bd810895dab74cbbe07c69dd440cbb51f573181ad4dddac30fcdd0f41f",
|
||||
"0x9b9eca73ab01d14549c325ba1b4610bb20bf1f8ec2dbd649f9d8cc7f3cea75fa",
|
||||
"0xbcc666ad0ad9f9725cbd682bc95589d35b1b53b2a615f1e6e8dd5e086336becf",
|
||||
"0x3069b547a08f703a1715016e926cbd64e71f93f64fb68d98d8c8f1ab745c46e5",
|
||||
"0xc2de7e1097239404e17b263cfa0473533cc41e903cb03440d633bc5c27314cb4"
|
||||
]
|
||||
}
|
||||
+22
-20
@@ -2,13 +2,13 @@
|
||||
"attested_header": {
|
||||
"slot": 129,
|
||||
"proposer_index": 5,
|
||||
"parent_root": "0xe32b6c18f029e755b0273dc1c4fa2bc4979794c8286ad40276c1b8a8e36049d8",
|
||||
"state_root": "0x5ec9dacf25a5f09f20be0c59246b3d8dcfe64bd085b4bac5cec180690339801e",
|
||||
"body_root": "0x4080cf2412d6ff77fc3164ad6155423a7112f207f173145ec16371a93f481f87"
|
||||
"parent_root": "0xc2def03fe44a2802130ca1a6d8406e4ccf4f344fec7075d4d84431cd4a8b0904",
|
||||
"state_root": "0xfa62cde6666add7353d7aedcb61ebe3c6c84b5361e34f814825b1250affb5be4",
|
||||
"body_root": "0x0f9c69f243fe7b5fa5860396c66c720a9e8b1e526e7914188930497cc4a9134c"
|
||||
},
|
||||
"sync_aggregate": {
|
||||
"sync_committee_bits": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"sync_committee_signature": "0xa761c3333fbb3d36bc8f65454f898da38001499dcd37494cf3d86940a995399ae649216ba4c985af154f83f72c8b1856079b7636a7a8d7d3f7602df2cbf699edb72b65253e82de4d9cc4db7377eafb22f799129f63f094a21c00675bdd5cc243"
|
||||
"sync_committee_signature": "0x810cfde2afea3e276256c09bdf1cd321c33dcadeefddcfd24f488e6f756d917cfda90b5b437b3a4b4ef880985afa28a40cf565ec0a82877ddee36adc01d55d9d4a911ae3e22556e4c2636f1c707366fba019fb49450440fcd263d0b054b04bf0"
|
||||
},
|
||||
"signature_slot": 130,
|
||||
"next_sync_committee_update": {
|
||||
@@ -531,33 +531,35 @@
|
||||
},
|
||||
"next_sync_committee_branch": [
|
||||
"0x3ade38d498a062b50880a9409e1ca3a7fd4315d91eeb3bb83e56ac6bfe8d6a59",
|
||||
"0xfd1e5ff5d4a15081efe3ff17857b1f95984c9a271b1c41c2f81f43e60c2cc541",
|
||||
"0xe1c97f93bb7352d395d1ff8ee29881572cb7eb5d71634783701171dcd30cd93d",
|
||||
"0x77fa2170ddbd89b15dae02f2e6cf9f76c8e00d1c4217320acffbe01576d0da61",
|
||||
"0xe97288e0627219087a024078d69445f34f0583a6350a7c3c40c39fd1fa6f8d68"
|
||||
"0x43276bee17fc9fba3f4866e902f0e5b5b308d79db91154bb8bf819973837a7d9",
|
||||
"0x5572348e13ce59446ca0ea7cfeed07579da05f121920a76559e19bda94dd81cd",
|
||||
"0x2d58adca9f3c742530de037f1933d6de1920ea4b68581613d4bc32b71547f221",
|
||||
"0x7072b3c6577cd5a89b3234968f316f54630bb97eafbdb59e5b61637a9640255f"
|
||||
]
|
||||
},
|
||||
"finalized_header": {
|
||||
"slot": 64,
|
||||
"proposer_index": 4,
|
||||
"parent_root": "0x0f7bc2353778c14c7f6dba0fc5fe6eec87228b0d3a5447b61dce67b4d9338de3",
|
||||
"state_root": "0xfeb990de653ce494c0a263f820eaf05a9300dbdc30cb6065ede602827bfccde4",
|
||||
"body_root": "0xf5235cd8c24f2695fc5b7989926305c10ad8cf5a87d62a739f675f5543df2ec1"
|
||||
"parent_root": "0xa876486aaad7ddb897f369fd22d0a9903cd61d00c9e0dfe7998dd68d1008c678",
|
||||
"state_root": "0x818e21c3388575f8ccc9ff17ec79d5a57915bcd31bccf47770f65a18e068416b",
|
||||
"body_root": "0x1d1f73b864b3bb7e11ff91b56ca1381e0f9ca8122b2c542db88243604c763019"
|
||||
},
|
||||
"finality_branch": [
|
||||
"0x0200000000000000000000000000000000000000000000000000000000000000",
|
||||
"0x10c726fac935bf9657cc7476d3cfa7bedec5983dcfb59e8a7df6d0a619e108d7",
|
||||
"0x98e9116c6bb7f20de18800dc63e73e689d06d6a47d35b5e2b32cf093d475840d",
|
||||
"0xe1c97f93bb7352d395d1ff8ee29881572cb7eb5d71634783701171dcd30cd93d",
|
||||
"0x77fa2170ddbd89b15dae02f2e6cf9f76c8e00d1c4217320acffbe01576d0da61",
|
||||
"0xe97288e0627219087a024078d69445f34f0583a6350a7c3c40c39fd1fa6f8d68"
|
||||
"0x5572348e13ce59446ca0ea7cfeed07579da05f121920a76559e19bda94dd81cd",
|
||||
"0x2d58adca9f3c742530de037f1933d6de1920ea4b68581613d4bc32b71547f221",
|
||||
"0x7072b3c6577cd5a89b3234968f316f54630bb97eafbdb59e5b61637a9640255f"
|
||||
],
|
||||
"block_roots_root": "0x6fcdfd1c3fb1bdd421fe59dddfff3855b5ed5e30373887991a0059d019ad12bc",
|
||||
"block_roots_root": "0x715b08694bef183a6d94b3113d16a7129f89fc3edec85a7e0eaf6ef9153552ef",
|
||||
"block_roots_branch": [
|
||||
"0x94b59531f172bc24f914bc0c10104ccb158676850f8cc3b47b6ddb7f096ebdd7",
|
||||
"0x22470ed9155a938587d44d5fa19217c0f939d8862e504e67cd8cb4d1b960795e",
|
||||
"0xfeec3ef1a68f93849e71e84f90b99602cccc31868137b6887ca8244a4b979e8e",
|
||||
"0x4028c72c71b6ce80ea7d18b2c9471f4e4fa39746261a9921e832a4a2f9bdf7bb",
|
||||
"0x75f98062661785d3290b7bd998b64446582baa49210733fd4603e1a97cd45a44",
|
||||
"0x6fb757f44052f30c464810f01b0132adfa1a5446d8715b41e9af88eee1ee3e65",
|
||||
"0x5340ad5877c72dca689ca04bc8fedb78d67a4801d99887937edd8ccd29f87e82",
|
||||
"0xf5ff4b0c6190005015889879568f5f0d9c40134c7ec4ffdda47950dcd92395ad"
|
||||
]
|
||||
"0xf2b3cb56753939a728ccad399a434ca490f018f2f331529ec0d8b2d59c509271"
|
||||
],
|
||||
"execution_header": null,
|
||||
"execution_branch": null
|
||||
}
|
||||
Reference in New Issue
Block a user