diff --git a/Cargo.lock b/Cargo.lock index 9d7718b..56e90ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,6 +24,15 @@ dependencies = [ "version_check", ] +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "alloy-primitives" version = "0.6.2" @@ -546,6 +555,7 @@ checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", + "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -568,12 +578,34 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.29", +] + [[package]] name = "futures-sink" version = "0.3.28" @@ -586,17 +618,28 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-macro", "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -621,6 +664,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "group" version = "0.13.0" @@ -1094,6 +1143,7 @@ dependencies = [ "primitive-types", "prost", "rlp", + "rstest", "serde", "serde_json", "store", @@ -1324,6 +1374,41 @@ dependencies = [ "rand_core", ] +[[package]] +name = "regex" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + [[package]] name = "rfc6979" version = "0.4.0" @@ -1353,6 +1438,35 @@ dependencies = [ "rustc-hex", ] +[[package]] +name = "rstest" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97eeab2f3c0a199bc4be135c36c924b6590b88c377d416494288c14f2db30199" +dependencies = [ + "futures", + "futures-timer", + "rstest_macros", + "rustc_version", +] + +[[package]] +name = "rstest_macros" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" +dependencies = [ + "cfg-if", + "glob", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn 2.0.29", + "unicode-ident", +] + [[package]] name = "ruint" version = "1.11.1" @@ -1600,6 +1714,15 @@ dependencies = [ "rand_core", ] +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + [[package]] name = "smallvec" version = "1.11.0" @@ -1820,9 +1943,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" [[package]] name = "toml_edit" diff --git a/light-client/Cargo.toml b/light-client/Cargo.toml index b5d8fd2..183ea60 100644 --- a/light-client/Cargo.toml +++ b/light-client/Cargo.toml @@ -30,6 +30,7 @@ hex-literal = "0.4.1" [dev-dependencies] store = { git = "https://github.com/datachainlab/lcp.git", rev = "v0.2.9", default-features = false } time = { version = "0.3", default-features = false, features = ["macros", "parsing"] } +rstest = "0.18" [features] default = ["std"] diff --git a/light-client/src/client.rs b/light-client/src/client.rs index c7fa8a0..4d064a7 100644 --- a/light-client/src/client.rs +++ b/light-client/src/client.rs @@ -459,15 +459,19 @@ mod test { }; use patricia_merkle_trie::keccak::keccak_256; + use rstest::rstest; use time::macros::datetime; use crate::client::ParliaLightClient; use crate::client_state::ClientState; use crate::consensus_state::ConsensusState; + use crate::fixture::{localnet, Network}; use crate::header::Header; + use crate::misbehaviour::Misbehaviour; - use crate::misc::{new_height, ChainId, Hash}; + use crate::misc::{new_height, Address, ChainId, Hash}; + use alloc::boxed::Box; impl Default for ClientState { fn default() -> Self { @@ -551,10 +555,6 @@ mod test { } } - fn mainnet() -> ChainId { - ChainId::new(56) - } - #[test] fn test_success_create_client() { let client_state = hex!("0a272f6962632e6c69676874636c69656e74732e7061726c69612e76312e436c69656e745374617465124d08381214151f3951fa218cac426edfe078fa9e5c6dcea5001a2000000000000000000000000000000000000000000000000000000000000000002205109b9ea90f2a040880a305320410c0843d").to_vec(); @@ -591,92 +591,56 @@ mod test { } } - #[test] - fn test_success_update_state_neighboring_epoch() { - let header = hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212b2520ab3110ab011f908ada0c1b3a1b35c53d9860d1464d20138e6271602e00ea876757d7106016ce83466f3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ef0274e31810c9df02f98fafde0f841f4e66a1cda0db01e241c7ed90c7fafad6ebbd727b14b7633bd336a97fc9761bc37b12aad0f4a0cc1257fae1a1a2648190df64c111671f764e7729157d87a6a75046060e937d53a0791ba98205dc99116e137099424fe843a0765cb96f82d2c597a43da570355351b9010003b2fbb5134f56fe987ffbd6bf693df76b135948febbc7f808dea7f70e3a59a2d7f8bdeed8263f57c7d336fd0bdf3ff9df186a1e557df4edd987f8fefeafa6f0e4f385ed7df6bffd57c1d75f5a8e95fe7ff45b2588f66cfc8affdfd4decc77d8f6feb97f2ad701308ff50f677fe79af5ae4cd4fae8c7ed0cd7fdcc3cd0d3feaf976ec2daebddaa766d8d9e689ff7f7bfbf646fa72897dfcedff9b57bf9cb1ff1e378ca85df3607bcaf2b65dc7fc68dfefe3f1ea73cfff9174ad7e82f73ed7ff3e4a09f9fd97d794777aadfecdbcb77bf7b7ffcbbdff4615c4314fbfedb6ff68959f3fa71efdcd44bff3e6f44b655e388bfd4bcf8fa11a95f67fbfff8eb2af9cd028402211e008408583b0084011b48aa8465ba3192b906add883010307846765746888676f312e32302e35856c696e757800000001a091a0150bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e295e26495cef6f69dfa69911d9d8e4f3bbadb89b977cf58294f7239d515e15b24cfeb82494056cf691eaf729b165f32c9757c429dba5051155903067e56ebe3698678e912d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab03f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a61dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d25685b1ded8013785d6623cc18d214320b6bb647598a60f82a7bcf74b4cb053b9bfe83d0ed02a84ebb10865dfdd8e26e7535c43a1cccd268e860f502216b379dfc9971d35872b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a517ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e8b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d788694859bb832254baf4e8b4cc26bd2b52b31389b56e98bab764a39ff81dad720d5691b852898041a3842e09ecbac8025812d51b32223d8420e6ae51a01582220a10f7722de67c1a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b741b218c5d6af1f979ac42bc68d98a5a0d796c6ab01b659ad0fbd9f515893fdd740b29ba0772dbde9b4635921dd91bd2963a0fc855e31f6338f45b211c4e9dedb7f2eb09de7b4dd66d7c2c7e57f628210187192fb89d4b99dd4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cdcc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a419ce2fd7544e0b2cc94692d4a704debef7bcb61328b64abe25614c9cfd32e456b4d521f29c8357f4af4606978296c9be93494072ac05fa86e3d27cc8d66e65000f8ba33fbbd1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce739e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d21ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c192183ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5bef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd0756e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd0f8b5831bdbffb860a1b2529dc7c1cb57e9b80a29d82ca0fafad5245fb7947158cc585b96609a8dfd005f2b9d111cad1d663d506cfc8a2cd2111831cb0863c5a92007a91dc504a32e496d6e3e392258e7fd47d0ed7e01a8448a1f9967fae814829c4104b2d2f27b9df84c8402211dfea0567d4dd0ea048881bb924343a4e69bd8164a03ab881739dd0ce5cde9c3ab13408402211dffa0c1b3a1b35c53d9860d1464d20138e6271602e00ea876757d7106016ce83466f380e863967543e27479ee79f33ab2ee5e276b0970a1565d96767e3ff55ab16ce0ac421983faa09eea6aa8e769fdf8182251e9225e39b3feef23a302ba897c41d20c01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9e060a9b06f90318a029bf36156df8e525f809db876705baae274b69205fd5716448392648e0941c52a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794295e26495cef6f69dfa69911d9d8e4f3bbadb89ba06f43ef7855ea56f036992abd7d992004d9fb11c0f16ac7efad79698cfd468c55a048f43cb851c8a35dcaaa6216f8f041da9e548f6b699b3b60bd095409044c4542a0f5ca7a7a61593ea62df7e100ea541399629e3f3f90975ae4127c2cf46670f029b90100f93e770a65dbd3dedfe67ddcfad59d7bdc5ca5259f7eb5bd97efe35b4667e55aee7cdd8bf2715d8b3baf7dbbd73fa3b3d11fd1790ebaece8ad723bd8c3bce78837acd76ef9e95c7cd5ecfffb97a21ff6b8f4a8f52af4687b60d65c6fbff7de78cfeed676fa37efb75effed979f5ceaec3cdefe7b4babee0f8a69e6f7de4ed8a5bbdafe8753ae8eef77cb363f7f7415bcfef79cfd35a7943e3b783fd2d9eb35ff6f7cd6b2b7cda77a7eefe6beff8725f1e7eb35dbd4f2b59e976768eaf7ff5e64f0f73fb2ccfd449ec7ebdfa6eff77333f5bfb7efcabe75beb7d2ff73e4b5ef1863f5a0333644d9f307f777fededc8199fd0eef6bbf5c1e7cf2afdfd9bf7f14a9028402211e018408583b00840108e73c8465ba3195b90118d983010307846765746889676f312e32302e3133856c696e7578000001a091a0f8b5831bdbffb860a79e04e92307a88aacdb97e1af9c99826690c90dc3fb83251f6506c48fb5a8c515ab7afc554408fa67b4251b9910545601d47524cd356d2c7a6cf23e7a857666a3ca20c7b26949815d00ad110a57486afb03ebbdc0e6ad6205efda248580eafff84c8402211dffa0c1b3a1b35c53d9860d1464d20138e6271602e00ea876757d7106016ce83466f38402211e00a029bf36156df8e525f809db876705baae274b69205fd5716448392648e0941c52800290f15f352f1012037a54e82bc7fcef239ba9bb867286089a287d100ecd737449b93ff0af15c13affebd5db2a6be4767192689e8bcc809b26b794d9a37468ec00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a024897fb02565f515fa9fbb541eae07a132473349842b34786a06ec2a0d6ea64ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942d4c407bbe49438ed859fe965b140dcf1aab71a9a0175af0ef466ba120d773ebb4e5cf28141d94efd6214e5bb9cde6ef206a3afbfda066cc81edf1fbd1f605d108d2b478fbe7bb0c38ee3e3e5650ae035efa563fd729a0e3431ac6ae4eee634fd6a1d6e45807789b94ea432bdf8f9f857545823798e824b901008e7ea3b3105f95d18ca860548c85a7efd518cfa69c238dbd4efebd9d241b25f1cc559715d455a3e533b036ad819aa6b19b695ea91c3b23cebd293dd0b2b6e0ec56458b681fe22f7d45eec13f82ae55b2eaf5fe7537677a8ab6641be7f43100c09eccb83e9a8fa79e8f2f853d47b34bdb194d8c61c8fb2e6f6af59c3ac658b8460f6bc24c028e2ac09b88ef42a9028cc03a3577c9af93d67beccf3771457b0bfa92d2112a9be46b607ebdc9e67a14dd0d6ebd1cf9c48b7738a67744b114f952d5a1227fc312292cce5ca1aea7c48a1830bbc5e00a95c934fbf350d5d69ea1ed3edfb3bd79b9c95528a33546f781dfebbc6056911153b0887ce359ef1c8ac9181a028402211e028408583b0083f9c3198465ba3198b90118d983010307846765746889676f312e32302e3132856c696e7578000001a091a0f8b5831bdbffb860a5654b7010dfdd178f3465135f42d28c9d435d60d0267f87b2581e1d7fafab606146fb70c620b1663b0d46e5d58ca1580913f76779e3c5ba65916db7cc73ccfb9a569e3165266c5ccf25240154aa60ff995327a2a8695a58d68b2105314ab370f84c8402211e00a029bf36156df8e525f809db876705baae274b69205fd5716448392648e0941c528402211e01a024897fb02565f515fa9fbb541eae07a132473349842b34786a06ec2a0d6ea64e801d548b699a7cee908420aac8d540a2de752823af731ec288b2774069730edecf3d4900535cf7714138d359177c9064e446a7730b9349b3d2ee0436b5072a855201a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080120510ffbb84111ab51df90eb2f90211a0890231389e1c4e6a2f6e5b8154ea372063ed7d917cf0d32d7a2cd21adfd06842a00ef48a4e0bae1cbb1a3caa52a05cd1bedf1e22dc50e680b85838b4c4157f06fda036e5ab2773e21147d9baff1b131278acc2c6d94fe9b23d9fcfd03723db7bc345a062e246491852309e16167a9d3bf7496bea6cf7fc68bdde6bac349afe27a228bba09bb79be4b97ec382e2f13c4e552e85c5e8712e4ce079a84a19aa5008200d5b76a0e731649692d47833e6cf7053d746ea42d495ba405c363e9b7d0c672c8c4481b9a0e9bc22e8fa15d085a68c3bd14b9a750d310e1680ac5bdfa386f850aaa67905b8a0c352465d5662ac5b77de54c34855ab9c4e808378ab1d645cf7a30a8cb51caf26a00f4cb91d858bb51b8a795863d9552e1f105f2e3fb37f1d161c1dae4b203a3c72a02e7905a411dbd014e64713312927471c4b1c3885fda3ed5888c0fb192e6de359a05e60aa49704b32fcbcd9543275600ba900547b31ddf446d55c527f09f0f5c6f4a08886a98f2e030a70ec24f9b1096b548005b64c88faf516361a2a694abff08ac7a0f072b67b389d8c065c6585b92a89bcbdb4440ae210060f7b98ac92d7b1e62f8ca0e8ee249f924ccd80781c6892e42a15c60da9175802153a0ac71650b02c13ee36a0a8632cd2f0beeb0f89b728d65d9ea803bdf0b12a5e3d27cbe5832e4ceff8735ba0b10c2c47b02cd583395fc5e70520bf57b97ea460f5fbf600049db152afa0ab4880f90211a00971b494845868a4a6f5a36939740537be16ccc185b7724bb249439267aaacc3a0ff26bff9727522f6773d888a48e2f444b020e62fce9bf0c6e15eafa0d7c3cb58a006aa21a0b04e596b5a4ebbb384309a489e876c1be7e7a2b02a584b4530d66925a03af99e922ded079114bf3a92f2a21d0a5dd131d15e0f3e01c6410974fbc3d8cca011114fc621c9378780c8ded766139c9c1c5f03a8de0747eb17bf337ea4a2ca2da0604f4775514cb56b34732652f20b49abd5c40ba4310353e3e0271a7194379e9fa00266443ed0582ea87a478be34336830356a001e40dc4a05d139348d794bc0ba0a0c8e7006ec197ab21c2409125cdcff2e78f29fea018eca902733c017f43ca794da0dcf51b76b1845f2b5bce3e5e2ecac30166b619ff1f18329ecfc49d1f3de50d06a037c89a9609e09d5b06e33b8abd35e3f9073bc6bced657355ff26a44a1fb0a361a08290bc67998f67791a82885a0cb0e81cac9f35e02388febf3952b7b5b79f8885a00f172f431296d1e299667720093d4d3ccd4ec7aeec24241ccdea49ea1688646ba021de7fd2dc90ac8bb698c0888ec4ff9c19f5e5748d46b49dd7238da60e7fc3c6a018c43df08c3e25d13db0b22ee521f3f450aca517916b5cd5219c86b49e49a044a00b8131712251baad84b82f2a44b8a4868ac8d87f03fb631130fce4be948ed9c1a068aaddcd50b8e792c89aecebcc859ec916ed530162583515aa71815f8542b4e180f90211a0c14274d28a2e70b696f18013ed25d6dbad53e4f055cc95d9a831c025c2ed9b01a0632636410cd51a3c53b184462e1e407a0422ec61d24118ffbf9aad2e0158d97aa016c98b9e76bb41d55d32c15e53ff870dce6db42be5e31d669c10f60b70409912a01400aa2f7e63dfa22e66c1096a7032502c24b261a52074dcdbaf7672d411c163a086ce70144b17c65c8a205f3dfd182959f0b1fd7f90143ad50e6999752832694ba0f8d20b759725fe897eb1f8987aff3e33e2bb00f32ebd4ccf2068a3fc89ca6080a044de2aff10255376ed36b22eff5590eb58d3ee54d0e4cc7eca4d22ee11bf7387a03b8d65e333aa13f8afa5982868e7f7890ba9e9d1e71f57b6d3a7ecee4482d028a07983b553b56cdc0305676f9622ff64df4ef45f1400af3a94ad08cdfa43c8a6f6a09bfea18d16df95e1dc70ce655d8bd283c900157317ac53c05931096c80967c93a0df5c3ffdaab83f24dc1c21b63a655880aaba83e13ba3037db17f53dab3ecd908a03e664ae0cd067a6ad7aaed8ba647c34e2cffde9104cf9d385f302c7fcd714f85a012e7260db92227621f4ed41a8e50582cfef95cbad9d1b22ff14b82d3c59d9241a0a42731a74edae14df8c52c748eefa4dc148b679ff88e26ece01a753247875154a0a9bf2ef8979a58da04857064c92f0ca860c12e1e1739a419faa1a7a179e6a575a0da31d47321bec6cec888e06e9182d2b579b470e53fdb241f1d7c78f88c65133f80f90211a07cd4b1279b228ef40481922604a05d005cf3e596efbb7eecc920460725ffc958a04d0eb9ce763d8b0bd7d77eb2c450b1d1a68fa9d4a39f74fca416ae8b021dc252a0c8d17bafc04d0578123e28fe318c024cd8ffc2919906c9a0827f1e790c63ca36a03ec45bc4463a145cf8c75f30f706e244a745a1b27283c92dd8e29bc787fabeeba041e3e5a0474e922690d384c4ab603cf6cae1c5333510c5489a0b9cebdf9eb16da0872a5c56d4ddcfab1473aa4b5187aec0cd9ad6be7316293ed93e330649e6948aa033e7f70da3e2514734dfd9f6e22139c326c409ef5a098342d0ca117baae919a4a09822c694761ebd9436d546b74cb8a3c333887e3794521ac7ea5fa7f130306265a08f93244365f1bbd3d34190af7531cf9eb3bc752f4a7b37e2454811675098be24a0329fd3766ca5e0ead8ad587c20aac5d344426a175907f80b2ed4f3eda8001873a0704b7adbf076be42c914ebb93045d9dba99269d719e72f716e5c82e1c4d30ed6a05827484fc8250b11323578d86af3b2d98db47949bd7fc670fe62ac6d8b2b29dca0c50f5090c95cf05867a259e409440a47bb221fc0ca50765ab452a3b448fa68dfa0ea739dbb4d387dfb6f0aa8f13a8eeae6aef55b21512cb046f5cf6bf142a61d79a02fd141d9061f06e999c896bbc7b1d4d652be24a710c4893e9d7fe7aa30f7cfeea0135be94cdf13c38d956f6e782ac6ace9b8cc40305249ac24dee470a8236e7e1280f90211a08d19750aa033c3351c90890a8f3ce2bde5f8be2b419c6f45115d5e6fa822ee47a0af80bd31da73dd38aa307ddaf4a3a4967139569111706d42284c59fd65e962c8a0feadc5dfc37b565bf229e9c73931d9f2274a762ccd3fad295ec327c6afef9525a0974634e6d38bbff1b17032a6566dbb3ff4d964ddf8fd9461cc13be120a4c79eea08d665f3fffbb6db4768102cb4c238b7082ea97f148ebe52a4a7e2aba26c7c537a0d9f11599f8cd8e41ea2799bc67598f702cf749be0a8990f096f8047fba2839b0a09be08e8044dc3057d056efbf1418467b516c8eb78b6d3c04aa69a7da735886a7a0f098ba0d8d2aa43642190af04c3fa97ecd8a2fdbeb5d6a2fa8eb1312176c763aa0a5aee8d8da8b6c01810834dee37121817b4a6889237bc060c1b78dae010ccb6da0495ff86cf6a6a9d9b043c204db77369e9e9d9767d6af4d963c05468983d12a2ba0a8e2263e1242397424b80e4e5303d95c34484426f63348c4346bc7d7878a8cbda02d6d70eda441d1c2383000a093400ade51ac7a04abc1aa99a7ce7b1624cb731ba0d6e684d598642afd2d7934c57123128ba3485dd00862b738e8f18355286f7423a0e09050c854d7a0d5bfcdd14f07043fed81662126e2701a4566c1d7a261900c71a03ac1f69f8e20a8792ea98d671e979a20b51ed4b37b40e2671dc05dc4d6653ce7a0598310e43fc8ee41ddd015d5d2764c7cd4959840260cfa7cef41dff52ac51db980f90211a0f87b60a82c2c32d5439e3199ad0c3a009a7f5474a027dac454b09effadd1fbefa016bb48376076116f468f16394fc6898356d00b458ed14b901461d1afafc89e65a03d50a67e8ec93696c35865d9f03814e95406c8d04e5decc320b9a24e5beee1baa042fe91ec49a406bb4a35b05a7fc518b915550848ba48afdea839969737e94d19a0fb5a2ac85aa55665e6a21b4d77a80693cfa450ad3db8e22963f12740f79e948ba0a32564adebb5029e48a91c8f6a90d04de2d3042b4a44f20e347bd68a26ab0cdda026c57b9b5218aee794dc9b3f90935ff1374ede5b73847c902ca61a1c41105e9aa02b22a7bb0d1b84b9d89fbfc571f0c4122bb12add28e944b047e40323fbbc33bda08a831384faa68f9caa047a6200464e11cfe5f9f700a5ed9435e5241d9d2a501ca08987636c0999e2eb3d052f145cd6b23f50946f6d737da20b5a7e2e1a8dc91c97a0e4fc7281b24a4a9d96dd4af6804d6276bc1c176d8e34979da2e7140310e66adaa06cf03705b25b817df44e3bc2122f8f49ca8aa80f32e7cfc5ed69f6c37ff49c2ea0dc66c764a34bf9f1c62917dbfcd1b930fd9b9c4379d520104519ab3e80f05265a004c43c3abc9e1ee7c131611fb29bf3e55705b91f687b5b30bdb6c5fccb431232a0dc32b4bb85eb8facf38af40cd4f77d9159f4723c939ac466e106a6d3c7535847a060dfd3aff904b5bb6d5f2e37695e05c9b935fab7888bc88486f6e811f606e20080f9015180a0c2cb770a3d18eb1214a782cc81b79a7fd772716c2d050ef66011095c3774e8f7a08fc7d7da06fba7ffa69b095aae41147e3a55b89644682057cedab705ba7aefd5a05975b434f69398107a4d1729f8f56e75247df09c65b1a750797818607bf118df80a026cea4c13260b2a1dd74bb6fcc7cc36162d2856ce691a36165c633ba68f7b783a0f7b0c667509a4ce937c487b45bc53c0700543daf4f8c127fbe475b4e1084d2328080a0454eca3fcc32afd4c4000ccbb47732bbce342b1a9d374fb5872162f2c873625fa0b3e6c44579a731cc730a5472e83c6098fa2943e5b2c72f4475f0afea76848a87a03b8c951788b8c93366aedbf88f6c1ca6085cd0249025ce542f19294b40bb92f180a06efa682f711f1d9e189193bd4248884cecfa463028d015e6086a7de0a0889b0780a049ba777ae33a75e8c0c7bd07597d6e6fb43624537a579b9a06b20c89d6918b2980e482000ea07b2632b8b97e159d88f112a8dd9d44df2f3c4502e0c79a29297ea7f61f41f311f851a030590b16841225b9590cdc95b19176201d442ca0b931c6e4314d20a1c772ea9ba052e8f9f247cd159c65b304863d444087f6a60d7dbec3a0e4fa09f007b5a1c64f808080808080808080808080808080f86c9c20120c458c4c09a9448628f84e81161b308d5c4041a3d3a1ea329d0eb84df84b0487400e8b4f1c9c00a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47022440bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e2244295e26495cef6f69dfa69911d9d8e4f3bbadb89b977cf58294f7239d515e15b24cfeb82494056cf691eaf729b165f32c9757c429dba5051155903067e56ebe3698678e9122442d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab022443f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a224461dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d252244685b1ded8013785d6623cc18d214320b6bb647598a60f82a7bcf74b4cb053b9bfe83d0ed02a84ebb10865dfdd8e26e7535c43a1cccd268e860f502216b379dfc9971d358224472b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a5122447ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e22448b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d7886948522449bb832254baf4e8b4cc26bd2b52b31389b56e98bab764a39ff81dad720d5691b852898041a3842e09ecbac8025812d51b32223d8420e6ae51a01582220a10f7722de67c12244a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b7412244b218c5d6af1f979ac42bc68d98a5a0d796c6ab01b659ad0fbd9f515893fdd740b29ba0772dbde9b4635921dd91bd2963a0fc855e31f6338f45b211c4e9dedb7f2eb09de72244b4dd66d7c2c7e57f628210187192fb89d4b99dd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002244be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cd2244cc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a4192244ce2fd7544e0b2cc94692d4a704debef7bcb61328b64abe25614c9cfd32e456b4d521f29c8357f4af4606978296c9be93494072ac05fa86e3d27cc8d66e65000f8ba33fbb2244d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce7392244e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d212244ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c1921832244ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5b2244ef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd0756e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd02a44295e26495cef6f69dfa69911d9d8e4f3bbadb89b977cf58294f7239d515e15b24cfeb82494056cf691eaf729b165f32c9757c429dba5051155903067e56ebe3698678e912a442d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab02a443f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a2a4461dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d252a44685b1ded8013785d6623cc18d214320b6bb647598a60f82a7bcf74b4cb053b9bfe83d0ed02a84ebb10865dfdd8e26e7535c43a1cccd268e860f502216b379dfc9971d3582a4470f657164e5b75689b64b7fd1fa275f334f28e1896a26afa1295da81418593bd12814463d9f6e45c36a0e47eb4cd3e5b6af29c41e2a3a5636430155a466e216585af3ba72a4472b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a512a447ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e2a448b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d788694852a449bb832254baf4e8b4cc26bd2b52b31389b56e98bab764a39ff81dad720d5691b852898041a3842e09ecbac8025812d51b32223d8420e6ae51a01582220a10f7722de67c12a449f8ccdafcc39f3c7d6ebf637c9151673cbc36b888819ec5ec3e97e1f03bbb4bb6055c7a5feac8f4f259df58349a32bb5cb377e2cb1f362b77f1dd398cfd3e9dba46138c32a44a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b7412a44b218c5d6af1f979ac42bc68d98a5a0d796c6ab01b659ad0fbd9f515893fdd740b29ba0772dbde9b4635921dd91bd2963a0fc855e31f6338f45b211c4e9dedb7f2eb09de72a44b4dd66d7c2c7e57f628210187192fb89d4b99dd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a44be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cd2a44cc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a4192a44d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce7392a44e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d212a44ee01c3b1283aa067c58eab4709f85e99d46de5fe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a44ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5b2a44ef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd0756e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd0").to_vec(); - let height = 35724800; - let trusted_height = 35724799; - let trusted_current_validator_hash = - hex!("97e642190471429a60b6964c475919444b7c9f8972a33507c30bd8d2c728745e"); - let trusted_previous_validator_hash = - hex!("1097f9094a26384a86fda6f22e5da7be996beab06fdb8eb865f5fd2b90b6f39e"); - let new_current_validator_hash = - hex!("732ae226da9beae0b00a2eec692956f0760b237f30f7b7e8ead93d92de794621"); - let new_previous_validator_hash = - hex!("97e642190471429a60b6964c475919444b7c9f8972a33507c30bd8d2c728745e"); - do_test_success_update_state( - header, - height, - trusted_height, - trusted_current_validator_hash, - trusted_previous_validator_hash, - new_current_validator_hash, - new_previous_validator_hash, - 56, - ) - } - - #[test] - fn test_success_update_state_non_neighboring_epoch() { - let header = hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212d15b0adf0a0adc0af90559a01b8c590cd6b9bcf6c24e47e5f6468083f6093d05f9cc6a3f45c0e61a7989914ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347941284214b9b9c85549ab3d2b972df0deef66ac2c9a03508e22b6e7dd679e544f7badb659cd936e1722f9a91136e800681d588b886aca01aa0294d38be68038c13ca83d122e765b2714e3cf5a7c8b382eab64f009be8eaa026033fa1fdf7e559f128b7380b369d908261c092e97040cd938d0c2cc83c8d52b90100000448000000b680400000c0c00010000280440000920200002040210200009000015e2004022110000830000800100000001222041000004000800040ac100004c0003004102013000540080008820021180000100482004041102000001c00100c68200202009509421005288a684028202400000408912000403080000c000040481c000c80141840181c20001004102084e02800200a040000880c18802006028010c000062808040a2022023082410200880080104a40e00011000000021410981200100a8000026900081200002000808004800420811049ea00206000121002c210000002491000941000110000249000809900084006210020000a00028402620fc884042c1d8083303e3c84663394e3b90337d883010406846765746888676f312e32312e39856c696e7578000000821df8b90808265da01e1a65d62b903c7b34c08cb389bf3d9996f763f030b1adcfb369c5a5df4a18e1529baffe7feaec66db3dbd1bc06810f7f6f88b7be6645418a7e2a2a3f40514c21284214b9b9c85549ab3d2b972df0deef66ac2c98e82934ca974fdcd97f3309de967d3c9c43fa711a8d673af5d75465844bf8969c8d1948d903748ac7b8b1720fa64e50c35552c16704d214347f29fa77f77da6d75d7c752b742ad4855bae330426b823e742da31f816cc83bc16d69a9134be0cfb4a1d17ec34f1b5b32d5c20440b8536b1e88f0f240d3256eb0babe89f0ea54edaa398513136612f5a334b49d766ebe3eb9f6bdc163bd2c19aa7e8cee1667851ae0c1651f01c4cf7cf2cfcf8475bff3e99cab25b05631472d76d76ee8823de52a1a431884c2ca930c5e72bff3803af79641cf964cc001671017f0b680f93b7dde085b24bbc67b2a562a216f903ac878c5477641328172a353f1e493cf7f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea99e3849ef31887c0f880a0feb92f356f58fbd023a82f5311fc87a5883a662e9ebbbefc90bf13aa533c2438a4113804bf980a75ecd1309ea12fa2ed87a8744fbfc9b863d589037a9ace3b590165ea1c0c5ac72bf600b7c88c1e435f41932c1132aae1bfa0bb68e46b96ccb12c3415e4d82af717d8f474cf03cceff28abc65c9cbae594f725c80e12d96c9b86c3400e529bfe184056e257c07940bb664636f689e8d2027c834681f8f878b73445261034e946bb2d901b4b878f8b381fbb860851066357eff502b847239dce4def537c09981995b09a20b0332a5931b6a80a0756929d82d67ada1699558c423a5108b0754fc4a8729fd2967822ee274fecd8742703f1e758c0c25aa65667ac33ca73a09dacf4ffeed749d956d6b438a65fe35f84c8402620fc6a055a683a5f4aec18ad180c783416fa6064fd77d12dd9cce6aa4e2d21814a1358b8402620fc7a01b8c590cd6b9bcf6c24e47e5f6468083f6093d05f9cc6a3f45c0e61a7989914c80ac0efe500470240a4e493ae2a67a28f2974da7a8b00ef170fc1d2357732a713d15528f7773b127095705a9d064c155484a7e3e8ccefefbcd1cacc960b3a0fe5f00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800abe060abb06f90338a00675a9943e5eee827641ecf76ccdca86c00760201e79454d7d70bf1d1229f4e4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479435552c16704d214347f29fa77f77da6d75d7c752a0f88cae15732bc072d88e3266e79c63ace19f6158d861b5a1527eecea8b3a0c90a0805f0392fd4fe5f40410188ae1823170f330fcbd460029d64100fb762c18db22a068061db6f72b36216ac8a6d4e7ade646d0481a5e58a1d446699f73f0000c65beb901000200000000000008100000400028002100000000101280100000602202000080440850000800001001020001000091010090200a10040008009012000080600042005010001000000010200880020010221000a0000208004a0c88000102140000080061090200800044000000000000080000000008088002090010040200040840000980000008000000000104000000100c200840100000000086001000200400000000008020084009000200204002800000000080008000920c0100000004880a0a0000004001810000000120124000009204080080001040c20000a000000030401000000201004004020001820000c00000000400480008000100a000028402620fc984042c1d80831a1f2484663394e6b90116d883010405846765746888676f312e32312e39856c696e7578000000821df8b9f8b381fbb86091ba1e6cf213db9c2384a8b80d1a61adeca1222451ad44989a3a4353c926cde613198ca3031c6b7c7988b0302c51f2bc1762f889d44c27476f73339069a6aa0b5fce63de2c6e847ee07c01620e47d27d090277ce3069e61a8e0e5dc75e7b6c02f84c8402620fc7a01b8c590cd6b9bcf6c24e47e5f6468083f6093d05f9cc6a3f45c0e61a7989914c8402620fc8a00675a9943e5eee827641ecf76ccdca86c00760201e79454d7d70bf1d1229f4e480899ca0f597006047cc915ce49e35b70eefe652a4f46d2cf8f9954323b29dc13a07ebbdc07dfa4f17138db9af8611fe9a98d289df90b46aacc8d86e6f39c7528e00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800abe060abb06f90338a06f8122b4b7c614859a61d8e12f236efc07d92370c52e9f3f8de48bc4c4c3f76aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479440d3256eb0babe89f0ea54edaa398513136612f5a01d6899d6d2e0f411288f145754d9672ce2881c44d3e9a25a6a33d5f625ec608ca09ef5f809e4322bb7ac0df0c4b4ce82d4fea1e31832734ed2286e1bbf3bcf5967a04f4875ba4450b51981ced70f5cb8ecfcb4f402a2ecca8f038ce9340431ba6677b90100100800080000000008000160000000240000010190000800000040000000008000081421000000100002001101009800001410120000000000001a0000a11200002030300820000200001008002000002010000000000000c000508001101600000800200a02009000010000000148c2080000000004089000080890420000000042000800000000100000011010001001000c200c000200442000801810102f060000000006a02808440000028000040001008800000018000082000000000204414802000089000021400010428000008000840280010100104142000020000010108a08040800118400060000010020208002201000024000100000180000028402620fca840427f164831ba49084663394e9b90116d883010405846765746888676f312e32312e35856c696e7578000000821df8b9f8b381fbb860ae5cfdf126fe914ba373cc010e894bdc02c34c113feaa7bf6e027879725858c3aa8740b6abb90f1dc389003dae1eb30d11aaead3c1df95d86bfe201cf0c5a285dd915f13a712abd523322712c42b8195c6cab1b5b0314375c059f48b8b79c8e4f84c8402620fc8a00675a9943e5eee827641ecf76ccdca86c00760201e79454d7d70bf1d1229f4e48402620fc9a06f8122b4b7c614859a61d8e12f236efc07d92370c52e9f3f8de48bc4c4c3f76a80bf2db108411fe95e684c82f738764633a2d29253d20c1832b7189b7a52f4c7ab75224c2bc89d3d1765b1aea4a347f2526cf24c4518ce3eae863383938cd651a001a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800abe060abb06f90338a0b8f6e83d72a579037a1747385d006303baecd2f9122ea38d7d7caeae4322fafaa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479476d76ee8823de52a1a431884c2ca930c5e72bff3a090533b33c3cc5cfecbd33918e04cc12957a3cf6a5844e65a0ca4f2ade2994b3ca0e6977483ef89448a9e5565ceff05271fd57f2ba905f9caad339902e605fc8db8a0465d7a4ebdc6f41f40124db3193e5a0565e6a877854715c5811eb143d1d5f392b9010002801044080080006022024040a0002000a840003012002810184001000409924008152008200011040240012c00100120102002000000200100020000a4702006466030020000000001000c00008000a0180000000000804241102800111710100c46a00a02009500060004288008400c000400081808900001045400020c400240001c0000000000000ab000081008001c0ea028028002042040800810202006480080400006380840100002001402010000c00000000002a08311208022021400981220004881000300c002035001000080808ccc0324001040420000600012383086100002080941c204000411810400800000c020004c08080080480209028402620fcb84042c1954832408c484663394ecb90116d883010405846765746888676f312e32312e39856c696e7578000000821df8b9f8b381fbb860ac51bacb0156bbd71fe9d754817bcd1ef367cd0a6ca2d719fd1f9294164e9ea536937167df9370e7e4271846d099f1c01785e38478fca04f68559d2740447cdfc8f8e1d9bfea1ad6d331b13c63d133504203d7b6197e59837128b91b568c302cf84c8402620fc9a06f8122b4b7c614859a61d8e12f236efc07d92370c52e9f3f8de48bc4c4c3f76a8402620fcaa0b8f6e83d72a579037a1747385d006303baecd2f9122ea38d7d7caeae4322fafa80995177c05ae18a7afb72a5a5b870aa4cec13dd3bec378bd0bdd45c8b32ff9d94379d0649899e58045bd798c90c83f068c6180ac3be527f5264fd1fa40d5f3f7f00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800abe060abb06f90338a0c1828f9fa73b74d490c01682f5e7851683736d6d38437034b118ecd99aac908ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347947f5f2cf1aec83bf0c74df566a41aa7ed65ea84eaa0909eadb50d8d80fed8719a8008f9a96a65105c9f9adf5f09583df44903455d08a07fa76502e2d2fad4544c010c2cb4719b07845b4ade4c57c05c194dbe35f27990a06c6141cf0821319308c5b281ebb93512f27f384d9d039387d765fa27ce7f5ab1b90100020000000004081820000040000000c400000202800200000008400241000080c0001c0000220050000000000200100000000082080000080000100000b064000000201000000011000010080200000020100000240a0400c000000080041700000804200002208000401000085000000a00000000080890000010140000080000400a0800080000000000040082000100000e2018000000000004c208100260060000040000003108081000020000400000004000000000200000200000030004000802001000004000000040101008020000000c06200000584002000020000018000010000000011100040000110280009000008080084400000004090000028402620fcc84042c1d80831f9f5d84663394efb90116d883010405846765746888676f312e32312e39856c696e7578000000821df8b9f8b381fbb860965d6d03c0493b4b7a3cf91fdbe7d114ebd38ce476e1bf47f1d1a55a8286408e61d2fedaac5e6c9b577f808ddeca453619c2fa244c4c8d0c521caf5148b532bcc376df1e5195419b11a350b03b596bbda029f1b074c42a3e9ce26d676c708c3ef84c8402620fcaa0b8f6e83d72a579037a1747385d006303baecd2f9122ea38d7d7caeae4322fafa8402620fcba0c1828f9fa73b74d490c01682f5e7851683736d6d38437034b118ecd99aac908b80e1175bb3858b24abde91024c935edf639b17cd3d48a67110b486064b018cc30273e32fc65969bdfaa4f6c72e0ead81230fa220f767d21f0a434ba82d9d5f6fcd01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800abe060abb06f90338a09c7cfa55ae4789be64a696d357083683dcbc0429843811c125087ffd383311b2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794f474cf03cceff28abc65c9cbae594f725c80e12da00e783cf76ba10af8b476c2af6f0099182dc3d8891e6bfe8ccfbd4df4df9e5725a05943a3797fc784ab2a933a7e8cf5502c66932b4d565bf39673d8c84a97e7c163a0887d4fd11bac9b67f2a36358099ecfb8a3777074a31a1b01b0a2ddaa1621e312b9010000010000000080040002824000000024000000001800000000000000002800a0002810400000001004020001084090010094204a010004000000020000a0600002000030000020080800000c8800080020100001000000044200000804405400000802200a02808000040000000008400800000000802000100008100000040001000008000000000000000000a0100000000420080000000008100010100021060000000004842008400800020080040000400840088000000002000000000004102802000088000001200000000020000280040008002000104062004020008010108000000000010040040001010000008000000000004800080008000000018402620fcd84042c1d808310765984663394f2b90116d883010405846765746888676f312e32312e36856c696e7578000000821df8b9f8b381fbb8608ce86edf055073ed3657cb976abaaad5fd17879de455c0261f75a68f1fece6134ccbbad1adb809ce0c8e7b50249422c212357367f0e2feca28deb104d6bbfa1a2dd080a66914b21756e2198cf1c52f50ad6edcc07ec72818f917e9d7111a6574f84c8402620fcba0c1828f9fa73b74d490c01682f5e7851683736d6d38437034b118ecd99aac908b8402620fcca09c7cfa55ae4789be64a696d357083683dcbc0429843811c125087ffd383311b280f18262798880d70059d643979022a2b63e4198d03f7b42b1b2ae3750a00ad54632f0755542d43c630c263fefea44700a9c2f5780aacb850a98fb22816843643701a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800abe060abb06f90338a0fe3e114a9b8862d981e404b7f83f43330e8a6a1d6f853b450ba8f358d8e594aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794980a75ecd1309ea12fa2ed87a8744fbfc9b863d5a020d51c5c97ddeaa92872cb51e57cf30cebf201e4455a7628909a944a153fdd29a08498edb273bef28ea8bfd2cbe9a99e2c94eac71fd9752a46178549e43b3dbb76a0af8c731b24f09013ae128678c593b89c686e5936789049da0a20a421f883e50bb9010012000008000800880000006000001000000000010002808010006006000800a200005c0000220010001800000000110100100102000000000009182000a06000020030380a0000008110000800000000a01000010002020040000000a4001400000880300286009880441010082008600c000000000838910000009008000800004200081000000c000000001000001011000c200a00000a040040c108100020060000040004006808001840020040c000000100000000010000901200c000080404681200100100000000000010000020400000041c000000104002000020001018084010010009011540064008110220009000001000014000980008080000028402620fce84042c1d80831f23d184663394f5b90116d883010405846765746888676f312e32312e39856c696e7578000000821df8b9f8b381f7b8608339e352db1dfd13827e415235e7ad9653cd14056bd7b78e93e09c86c36679ae02e13a2ec4aa1d8e2546fb5655f621d6041c1b9aa04ce18b41b7273fbab06eea3aead2ab3c6bdc791bb6268c781267b4ec81143312f419a48422eab7e7d8f1ebf84c8402620fcca09c7cfa55ae4789be64a696d357083683dcbc0429843811c125087ffd383311b28402620fcda0fe3e114a9b8862d981e404b7f83f43330e8a6a1d6f853b450ba8f358d8e594ae80b25e98a9d4d947ccedfd894f38dae23c09a3f30ea5b513470d75eac608d15b233c39278b14601bcd777c2f0c61fba173b2189614ff7ab761ec48e03ae2894eed00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800abe060abb06f90338a0ad80590a86e436e79aaa961dccc29d85d1304853ded12197ae2dffd42e75fa18a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347941284214b9b9c85549ab3d2b972df0deef66ac2c9a007e946b785a9637930533c6df8d79bb93184e47d65d28f7854d8c8ce16c63c42a015de33fa37a8bafb7578c335909aeff2b2b679997e548ee1a8d9f47a892ab1a7a02ced64c3059d0e81f236cdddfe8d034d05a08e1fe845ba32b4234d5ba8a377d6b901000000200400082008c2000a401000002000200a00103200000000502340000080002c142000000010002300818280140080100002400408000010120000a03000040000108400000000011108020012002210000020020408c80a100000171600020800200e02008001e00001200008001a0001000008089000081014000002040040000800000000000000000102000000000460080000000000088108904866060080800004006008400200060000400080008000900000a000820800020102040008020080000001850008400200004200009004800080111040424800a0000018204a5000020041000015000001020000810000202008440000000000c000018402620fcf84042c1d80831bb60084663394f8b90116d883010406846765746888676f312e32312e39856c696e7578000000821df8b9f8b381f7b8608e8cfe0b055b18d322025f0837aba5e1928a13f666255b83cf0529ed987b9b4e449d6248796bf8a351bf21cbeb4d869b14cfe57601beae23fed96172aaf53b42c247caacd125e363c7d4a36497c20523a72100fc4bc1a8f1db3ef66f882b1b84f84c8402620fcda0fe3e114a9b8862d981e404b7f83f43330e8a6a1d6f853b450ba8f358d8e594ae8402620fcea0ad80590a86e436e79aaa961dccc29d85d1304853ded12197ae2dffd42e75fa18805a390422f87c05ce81fad47bcbabb415c9bec71cdf4d6b8878409322a810d8567ef061cec5384ec4e0a754413ce28e6fdd24f54e84706337e863fef60b2489c100a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080120510b89c88131abe1af90d3bf90211a05d54f311542dc86508c3950fe9fd0e42666c4b0d2da357bf0ff5256206c4f499a0de4549196246f89565153fe5c293bd86825c81bebcaf5d863bc20db5b80f39c1a04260cf26a849cc8ae7d9e9490a0f3cae30ddb388a52bbb4381b648c6927f5d02a01043cbea73d2e4dad6a3021744ae80ecceee3fda23997f7e5a56d30721d6a89da0016bc5f3d3af4289603df49b9156999c4b3fab779399bba9dbb8d98a7d5fff36a09f7ae1ed754c036e23f8cee8168086eb854e9a74e50f80fe6eeedc06652d65a4a0aa0c44232305f2d9c73f4198c114a79f935d4f15479dcd8d61ab3fe5821608c3a0b2afddeb92bff5ff52f0d7d432e3b5e2c777988181eef046d4026e23a28a15fba02a6282e9d54cbe11efd2a4a36c899aeaa7cf7604c6c1d496d4ec36b26870d945a0d7c965d118cacf4d7282ee52216d42b231163efbb82fafc36bf6dccc2ace3b53a0e05dadba137f39580b713d54564bb2ccb48a4a4e882ac673aa972f6b4a7e2c84a0e35f8dffad08d4c9df98129ee14a657c0076c7e5ed00fea40d7bf4f9ae07c2c4a04a9dc6bc9c6a276620ccc29879f3e4195951f720322b72f3925c5862c5972487a06a7b7c9de98a1f4d36cf112f45b71e797694ed5b0c8ffcdcea26ed337bcea62ca0904b2f7a0c508f1876c1ffbba7832ef5babe8218fb7ac12d0f9bf4245b356a39a0bc5622b08b6882c64c3fd5ca4feb7cbe7845c911b3518874784719dac87bf31380f90211a0ed46c5f969903bd014b453e23bf036a0807d974ac245d974bea3edbfab8998f7a0fbe185c3ad730c361d61adafbf283c230a9e04a6971a5693a58b95d54a91dc18a01c49f9acbb2ef6407d5d88ad62c7e41c0ae4e1a86453d107f8b88e366e6f1f27a07f263e0e9ae17cbc40f87c3ce1249a552a18c5dc0b7fe42e43454663ac9d4a10a0ef16b26fa26244501acfcc480235d9fd3859b0511b1d840cb3960143eac49e4ea05e19c98be009508b8132d6bc03ce932ae80c584fed6c8b66690f51b6706c6110a02699c04fa558d4cf31a72eccdbd6c9b85921b18e92be8013b16bbbb0e0243d95a0bf06ce588155b0a5b8dd34eeb8b34d1ab6698da02bbd47b8df956f3f8f958f51a0105ad803a3be71de2802142849753f93fe3445762ccdccda5baafb2c350fe8ffa06e725a7130ddbff26e37c27c25830b6c3fac3575371cd00d26e799c30cfc61e5a045a5861fe345d073abd640549c0bc754f98a15f1349dc94ccaf8e366d747e800a01fa1a61b7b9716a711f42192e558ba2fcf059d8b87ad67cb4c73aa65bc918226a0e3b653f8469bce44931ae9a2f88c3ae385b70bae52b43902b618a0e29694dd8ca09f207e2e88901b54fb464545a33764841152a2669f6668610bc3fa10d5cfc2bba00393790748f68bcffb6f9e01a409b9d1e691406b635a1cca73ae061813ac4d5ba0c3f4178174074d467324173d8436674ce6c69fa7c49a4337a000635fb04dbf2380f90211a079c04022f20db8c5fcf561e1956bfe73e94c6e4cb2655ff506c2e298f1ab8f4da0c0c9908e024252617bb968a090881f478cf2cedee6762524d4b2d3521fce7b30a09a502add7d10c7817db9157721c4b03ff3327415d6d3b0307b11efa07a2ca300a0911e146a2367ecc6ea7dd6c2547ac9df60ead03cd1d14ddb3350b3968c7fca53a05cd154e740f91a9fc1b2b780c47cc5f525efab2e7c7c36248a2833a99206f291a03761f080edb655d24c234da08813efc750a093ea75e9603d558dd2889e254363a0035ad7eda8fb804cc3b2779b0f3c40e67f5c7fef6b354878cc659bb76c02871ea089848d6e6e0132be50e1428656da8fadda12cb411681a9cab7d5d9371650f2e3a054ab857606b93e77c264d3ae1c75bb7d8e532a75823fa0646934c6b07587d97da04303a53d5b1cf36d7ca5b3a35ff11b210b7fab8f2bea560fee8e1dc49863af08a083b73ad7bf82dc689745a5bd39837939169c725f44b3bbe5c2b9470c557cb6c1a01eb14803b41ee30b3d9256decc6b02f7b4eac0cba1cf60c7e806aa145dc95c3fa00f46a8879a158446fd5281f67942859516c094afff5c862d7925e28e0255dc1aa0a88775f84e8812564ca66ffdfc617993b642e48863299520f34c9e4f2b394b24a065a8676f56698d3c88c8360411a1b5d89cbdf44cef98a51fe1b761ed82177bdda0e9216b548ea5ad232ccea4285597ba3345a53d39fcd61de9546c24725edac4c980f90211a0fd00080f96539f8eb5a2b403c9594f7bbf1a9a773c9a4430d86ee7f4fc67f041a083d0f27ec441ee36c6b0479c30d213d373edacc372fc3818fc98eac3c53da4d9a09eefca974fe868babfc32bf6e1449d97d14a891e3b10bbe54f64e00a0b5dcca1a0ad7b3367ca39009b957a1825269c78ca3af9a2a87c43894fb8bb9ec165d7a4bea07b68db0a8ff70d3557ae4c04b964de0fb67e3c340f3649c0af4bf79b86e73be1a02af8fdf09ff77e7f4d0e325050a8f293c08d2cb328f8d3da7e083a7d48924224a032a90f4a4456c9a1cefc92ea7026d74d9c1c5117e8b7d405e9d9440a8edfefbba03c40b1884e0810d2d3579d8be5483a651ae4ea3041f484ddef2f0ad5a70efc06a06c34468de46e1c6fd59005d0201b3de36cab1a04daf1b42073e91fe35cac978ea05901b53bc10fe26bfa1936e1ba5a334d168558454429aecd803d3e63304984dda08e3a481bb8b089125b4e820bc9e59c606c47631394830b9b37c06c77110bc512a06411f9d1b96b36d413236b20ecaa77fef4bf17c023b6a0feb143a7dfd529053da0c388a4b630d106f22778df9782863b29cc712d25423c704117a9cd46190d55a6a0c3260e27d68de22e8dd36e2a15055e3f9cc0a1503510f8352be2458ce2849cf8a000d1dc7f94ab884d393c18ad9816d364c001e8ed29b5339d7d673d05d8cf8c18a0cc90581b3014a0af5d5a263a6581f442d75cccfce15f6da447c30aa3eee35adc80f90211a0f4f253a2981255c3c0c2b023a074cf35ee982c4709fe56d3cfbcc0d2d3e9e060a0c97e5c55396e530fb20bab042aabdf2883db66f41abb6c71f8eefdae67334800a006d2ac360ebe8eb14a59e2cccd35c3a23d9c559f183102ebdb3db068fdf6a634a03a78bec1492adf068ece5e9820d72df85d2e0b2b992f0cacb7198fc956473d94a0eecba4d8055f6358c4ed0989fbf575de5f137c4ffc73a53ade1d708c45641131a0eee901dcdf7b3b76f230c684200e990fc2284b3a3cac8156795643a8bf45f543a0c679d68e57dd545e7489f10898128a6a90ad7df29d3380ea3fa2c8d036a714c3a063062d6a6c1cfe1efff0e6965a65446b61982e763eb36652e1423df1fad08643a0d6c8ae23af8ad991e84c43f69bf280c54fc3a731b210bd60f5b8f39043480017a04614a62c039ff880d7c65c891e6fc6c55bf81bddadb42b5171a8d07f7218d7c2a0bfec07e9660db8afc02cd6cc2524246febc098f596a717190d1ef155317ce046a02aec38d6659b1b72f03b7b80e078dbc40650cea494f56606154538491df2598ea0c75fdcc0ec88840ac16c38f4a5902dc1e87d704cfdcec825b0aeee25fac08c32a0e09b0acd86da73ca9edd0ed45f52e970c710860aced6d2e1bb3617d45d1f1cc2a0bd67f755acb481bd586d2adae80b8155e8c887452ff964c8dd0ac888032b7d1ca04f03b5b8ef01c49629b79e51438d92a2dd9a490508152a96787ea1c39e1358e180f901b1a0b253f4d804466eedf2500f7c56b7b5c81937fd8547fbe942756bf1c2974245b9a0dfb6b4a54ee26fb0acc8a98e28efc6a9bef48610921ed4c5ddad4a6770ec413780a0e5b8323277c3cd8b0da5297fc709533d25bc28964698a6f2cbc4ba80c4c474c880a0ad4e25adf77388513a19b6e66f340845f4da575e05cbb41ec3ccacc962beb934a0ec3b2876d5a7b8fb4c959b2e2efd9a3fee75ee4e65da5438010367610ca50ccca0316db872ded9164c79a846190e57eb2c3a4379087798b8e1220b3cc5ff5aea06a05ad6bcb5a22ccc01a7b218c06c217b5c6f6a54cd77dbf3385422f37c3a5bbdc4a039d08aa5ea4684c934cd1911177ebea1f2f3438d891da946a0396ac10b663b1ea0c73d499a0e4709723af701832cc2e07949df500d5a817709746c124757f2a46d80a07967cd6ca41b76eceb64c5373d85399a380af1d1eae78f56a33a149677398df3a0753f05888f5454aba005e67e1061a0bbb982c308cf90a89746abebc76f640d44a01eba4f5159fcb36c5bde7933e2632b0923167fad080618e90b90e98f450e0673a0dc9282be875f1e21a4245c23816f7c36bfaee11d34c472c29ae4576985f2e9e880f8b180a0f53d8c2cc17264e3f43339e6390b3de4123e0d3014e2437d51e9527d32531dbba00cbb4e2b6e1f2b59fb98c96cd2ee4a0a9994e91d18564b8289c5dbf42d653e6a80a0585dc8b79c33d7f248c845ac6c35ea102dc2fd2870e4e96ae7891ea6093b3e6880808080808080a05b8b9aed0df2c69df192889f2a5c791f16590efae13338ab7279ea1bab2fd0b38080a07308e7b9a6597a64d45bafaf4b3a2a4525895d77c7d8c146ef7720f5c693f7b180f86e9d30e1120c458c4c09a9448628f84e81161b308d5c4041a3d3a1ea329d0eb84ef84c588823d85d5096750e00a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470224408265da01e1a65d62b903c7b34c08cb389bf3d9996f763f030b1adcfb369c5a5df4a18e1529baffe7feaec66db3dbd1bc06810f7f6f88b7be6645418a7e2a2a3f40514c222441284214b9b9c85549ab3d2b972df0deef66ac2c98e82934ca974fdcd97f3309de967d3c9c43fa711a8d673af5d75465844bf8969c8d1948d903748ac7b8b1720fa64e50c224440d3256eb0babe89f0ea54edaa398513136612f5a334b49d766ebe3eb9f6bdc163bd2c19aa7e8cee1667851ae0c1651f01c4cf7cf2cfcf8475bff3e99cab25b05631472d224476d76ee8823de52a1a431884c2ca930c5e72bff3803af79641cf964cc001671017f0b680f93b7dde085b24bbc67b2a562a216f903ac878c5477641328172a353f1e493cf22447f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea99e3849ef31887c0f880a0feb92f356f58fbd023a82f5311fc87a5883a662e9ebbbefc90bf13aa533c2438a4113804bf2244980a75ecd1309ea12fa2ed87a8744fbfc9b863d589037a9ace3b590165ea1c0c5ac72bf600b7c88c1e435f41932c1132aae1bfa0bb68e46b96ccb12c3415e4d82af717d82244b71b214cb885500844365e95cd9942c7276e7fd8a2750ec6dded3dcdc2f351782310b0eadc077db59abca0f0cd26776e2e7acb9f3bce40b1fa5221fd1561226c6263cc5f2244f474cf03cceff28abc65c9cbae594f725c80e12d96c9b86c3400e529bfe184056e257c07940bb664636f689e8d2027c834681f8f878b73445261034e946bb2d901b4b8782a441284214b9b9c85549ab3d2b972df0deef66ac2c98e82934ca974fdcd97f3309de967d3c9c43fa711a8d673af5d75465844bf8969c8d1948d903748ac7b8b1720fa64e50c2a4435552c16704d214347f29fa77f77da6d75d7c752b742ad4855bae330426b823e742da31f816cc83bc16d69a9134be0cfb4a1d17ec34f1b5b32d5c20440b8536b1e88f0f22a4440d3256eb0babe89f0ea54edaa398513136612f5a334b49d766ebe3eb9f6bdc163bd2c19aa7e8cee1667851ae0c1651f01c4cf7cf2cfcf8475bff3e99cab25b05631472d2a4476d76ee8823de52a1a431884c2ca930c5e72bff3803af79641cf964cc001671017f0b680f93b7dde085b24bbc67b2a562a216f903ac878c5477641328172a353f1e493cf2a447f5f2cf1aec83bf0c74df566a41aa7ed65ea84ea99e3849ef31887c0f880a0feb92f356f58fbd023a82f5311fc87a5883a662e9ebbbefc90bf13aa533c2438a4113804bf2a44980a75ecd1309ea12fa2ed87a8744fbfc9b863d589037a9ace3b590165ea1c0c5ac72bf600b7c88c1e435f41932c1132aae1bfa0bb68e46b96ccb12c3415e4d82af717d82a44b71b214cb885500844365e95cd9942c7276e7fd8a2750ec6dded3dcdc2f351782310b0eadc077db59abca0f0cd26776e2e7acb9f3bce40b1fa5221fd1561226c6263cc5f2a44f474cf03cceff28abc65c9cbae594f725c80e12d96c9b86c3400e529bfe184056e257c07940bb664636f689e8d2027c834681f8f878b73445261034e946bb2d901b4b878").to_vec(); - let height = 39981000; - let trusted_height = 39980600; - let trusted_current_validator_hash = - hex!("674c4f3d0b24204759cd9b4d9a641bdeed6adff81bafe9965451045916b6b4de"); - let trusted_previous_validator_hash = - hex!("efa11eef8adc20d6f179dff684c16891761d632462147830cb45579589632786"); - let new_current_validator_hash = - hex!("8a4bca6491ec89e201ea0e2776f0ae42f7e5c8d67a305a7aa6284a0e0150f736"); - let new_previous_validator_hash = trusted_previous_validator_hash; + #[rstest] + #[case::localnet(localnet())] + fn test_success_update_state_neighboring_epoch(#[case] hp: Box) { + let input = hp.success_update_client_epoch_input(); do_test_success_update_state( - header, - height, - trusted_height, - trusted_current_validator_hash, - trusted_previous_validator_hash, - new_current_validator_hash, - new_previous_validator_hash, - 97, + input.header, + input.trusted_height, + input.trusted_current_validators_hash, + input.trusted_previous_validators_hash, + input.new_current_validators_hash, + input.new_previous_validators_hash, + input.expected_storage_root, + hp.ibc_store_address(), + hp.network(), ) } - #[test] - fn test_success_update_state_non_epoch() { - let header = hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212fb460a9d060a9a06f90317a0feb3dca8515ba663608be132579cc4be830849c364fccc90d3e46b5f0c23fc41a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479461dd481a114a2e761c554b641742c973867899d3a023de09bdc6958b6144faa67c37966f2c1a8fb0697fb99b9e6a2340bb5be1dd05a0c834461f3fb915a33c55976be1bea82c54f7ff96ee284554346daa86d89d9806a0c61679f1e18d68a25b8598d05ae895768c0d6017198393f4c07d66b99221d6a4b90100812bae02ce1014d8885402d4ac1c150f9309418024012028ca0e4b3002c21800c01132417004ce41008139a008123203940e301980880004a00204d28d2420c2a42044820fe40060279d9f3cb14022f621d0126107668247210414058f206360b0fce6238a17002445cb199001c04d490a208041e24044aa2a00e710a4085101c51ae300021aa0718288a410e4408ad84c246c0528238048b510c044082940230b9a20008e22cda1260040042a8a0310040042023e88018583a235b068531469e30f045e04ac49c6809404a033105080200160809122403c6913704ea705f0aa2398a101b0c4d12253200ac32a0d099de93ae02da97223c811042a600c3914d0028401eab9cb8408583b00837a7f0d8465168255b90118d88301020a846765746888676f312e32302e36856c696e7578000000b19df4a2f8b5831df7ffb86097df3baf86afba3c26f7f97e49223d62fd9c09d728fe214d2d06ef9f7c3416fdc310be297444b7f4b0ff2835a02858e407d574343436f249ebf617c094c80bbc5d19341fb4ea8c7d9024480f16c4856edb087c3b7a06b10c38920a43c8753fccf84c8401eab9c9a022c32b836e14bb6b733e91900715e7268b23efbe462314fbc500d36b425ba1048401eab9caa0feb3dca8515ba663608be132579cc4be830849c364fccc90d3e46b5f0c23fc4180d25d99399c6b8c0339bcfd6b516fb1f3d2413efd792cf3c87a7c34ae80ca147934267791f4635c5d3840c11b240696e9c889ba0ec411388251026105fa7e5eb201a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a004155d7b8c18f2d69800c8f9444b4a25027c23eb7514ea0d3c646693d4673d99a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479470f657164e5b75689b64b7fd1fa275f334f28e18a0dd5169230dd630e4891f1356f1b96707176e5922adf7d1607d6235eaddd50cb7a001c548e269165c55330607dcaa0a13c7508ff56922757219a9050366b5833115a0224fc94974291205e108fdf540928481aa6ff640ad1ed67db7ea087dbd557bc9b901002a708b2a016850920a010e649218000223074a82c918008039019b851244021ca14931207014d88000404308001e20048a00581b10075420834024022928a2802c5042018540040041489808e0a2583c25182376014e0a4124c74210388301b1466ca5219e121828408108888b03c90308086440a84c04b93200c09c031425074709ca85a248c44e908b160088404898602e840438420868015080410009c460c69000006b66aa80806844440e42900370b2022098820a18100341e0c41286080881944a04480a871c2044418210d22020742940b808ca140d12548a0312a0001030ab0d016c2d2801318ad0080009680c2804f40468280899616f010a010140028401eab9cc8408583b008367bf768465168258b90118d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a2f8b5831df7ffb860abf70f41702762f51619c42bdf6b9c3ba383175632b6db3cc238bc17364bf21562a51f228f68534e7b4aaaff35f8c5ce08fd5e8dfeaa328a76b0e6ebb85b5e99099b660ed69b759f014fafa7eecb3098292d75f82d0c471ef6f9511b4ef3f8d4f84c8401eab9caa0feb3dca8515ba663608be132579cc4be830849c364fccc90d3e46b5f0c23fc418401eab9cba004155d7b8c18f2d69800c8f9444b4a25027c23eb7514ea0d3c646693d4673d99800b315cd2d4e3162f9ccfb0a1c3bfbf57368525086dd5c0b18bad6833e2bfca3e1fbad1657e623968d777fec26778fd846e6664bbf5eac859dd09eae74d96bee200a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a0dc9fb461ecd0a1bf6349e94d61f78c783a511d0e773154f6593f2530dc8c5cc3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479472b61c6014342d914470ec7ac2975be345796c2ba0b4486492538ac1aba093c1b5f303d47fdfc5be01cd5c67380e5e9760779139d3a037c90501705e0938b684c912c4bc8a2ebbbc46f477abf481e600262c733451d1a09219073211ceb3d89b20b19264464a28229a069c832e751f5452e7fb8b5efb60b9010052a0a28f26cff3f5004e00e4a39a044e8b084a42b48914c87a398316d3482614a6d2125560fbc0015063baf2041e401abd4bd410581be876371c29bb043e0a48864f669223440e39897b28298560542d7218016b437cc3aa28b6519482202e20c96cb4a98edb1d8f6d078b90c32c2b65ae80c41d0ee0c4ae9051de93c508e65082fcba04803651c7d3bc3482590a081c2c3c45c1ab33105930ac83405d02c530aa11d10553c30a14129042e4638214b96609149c6ace47e294644462e18acab0990b165ab81418225420106d0e34d160747963e4b182515451185e87a74be270b331ca0531290e2889276f12b400090a7900008d932867ce1b6fad1118bb520b028401eab9cd84084fe2c683b2b318846516825bb90118d88301020b846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5831df7ffb86099ff0d5d682bbb7d7a82a3e81c09b9fb4c3b3c2cfcc0f1b1d68ae90a678bbba5430aa814fb2102d6893c39de2e86c96f19d8d1e8cd93a5f86dd87c7639adf3f661e3ae238daa85243e03e8dee02e45d64556263c7b9d38a9fd250fc47791dc56f84c8401eab9cba004155d7b8c18f2d69800c8f9444b4a25027c23eb7514ea0d3c646693d4673d998401eab9cca0dc9fb461ecd0a1bf6349e94d61f78c783a511d0e773154f6593f2530dc8c5cc38040c23bea0a66f1eb621da3fd7184780591887e9a85a0b075a1df3e0cd6e14d522f9b3245bac947cfcc959770a65f63115fc2891b2043f675ca4e9e4aa6f2baf501a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080120510caf3aa0f1a951df90e92f90211a0879fbf1597c6a4a5c19795c1962370cc6de1ff693534c7bee22df95842990dcda0b22fc1e58162520af9a6bf4326027e307cec4342c9c3a6a9d6a32564363b0a2ca0f1654bf9e5e926a80711aff2934e073cf4b103765f9df3b069f24aef4d16cdf1a087c5469547200128d2c98237b629189f162e786bde24b500029235ec2ca89281a0e498ce1143f8c074010db7643780a87780f7578a41ec4a0f3bb2251369d68d46a0d3c655057035d5002eedc89b56f66bcf2d1b6fa8be67bc41d3c89be1f7722c4aa0284d823ebb6f34818f14ecc532b770540712f3aa1ca4df74e334bc253e6b32aca0f28ab40b0509b25fe9f3dd65f626f42729f52ccb9685b61b867469a321f21716a00f76ce464832957ad288c150ba1cadb0e590f316076a52a3344a37e70123c51ca0f02904295ad311f10ba192a1049f4816b40f7c81c651c88b110136d02e638f7ea021b037ac53fc4ea00c1da756df5fcd5f73fedb991cb716bfb9f946e07979833ba03144039e8987b82900e059f5780412506b75769f3b68609775a46112091297dda02641eb6e6277e93c4288f92338d04e51b4ef75a709852f73419d9da61c618cd0a01b65d747629e22c321c27bf3a3be57e9ee06e9f51193e8fbebfac66ad0e3abcba01cf92f3196475026a7c231bbf0f12cfc1f08b47fbcedc2a7c57b64e3b3832dc7a018767613ec3bea5597898b1dd2601c931ffcf0115547e23f84c06f320719db6980f90211a07f9d3901b46ee6b732d2aaaf84d40b47ebc831ed47adb8a2c1c43613de4605dba027cb7f21a746a9c6e76b3d4d0cc1da32111ca20b0d3f1cb64afd1d0462e8e211a0052f5245ea659debd6f38fc4789cbeb0fd2235aff77537e808e0e767196e8b7da0af67e75eb2f83ef984dad98b2e2d05a1b9e0d18175e7882e9ceb847c994f89a9a01af6bc0e3ec6cc384dd68218ed53f2799024d57d2c3a53523dfa227128699ceda040971b58d91a4e17e12065b5ee59134aa12173a581716893358ddb80ccd76486a0c68ac43d0dbaa844b812b91c527f70595d1c9fb33e49e373993078a9b6506f4fa0542841b0417994c8e689d15cf3d895a09d1e485ab9b3bf0b782b112792f459dfa09c410eeb054c0cd4bdcebab79f3dcd445ef33994e03b4f8336b1a3842c879261a0317498b85f2e60d0144557a9daa665b04858f6d67afa4692f6e40b518becc5e3a03e15531394d36f2cebabf69de2823a5a17994e85f6d4bc663947157c007edee2a091c0de5ac4131c6e9a625000d994dffb70f87eaa0dddb27544e731e2e04a066fa023ce1490b59b94bd8840af9c1a12f2f98f9537ddddee037209dd7881a114052ea0c7e8afeea81b08c7b07ab41e191b8c054baad1231db7585084ac90907211fc2ba068e094995972c8da18e345180551c04af0696b5b756d3f414dea3b41a15b575da0e22741ba7909396a84d3dbef5aeba6e6614638253a7319ec2fa6409cbde44b5180f90211a0e6d6c23fa1734c2f5d243a3cfb0f39cd02cfbfdb4bc3c8f431aed32fcd2854dda06bcf17926dad58b8c5118d5a6174fd085d03d92a9d4a5ed56efdd36f45975ea4a0f753573922dd3666bd8c5dbd5b4ce6de8a8f0800188c034d383d8916a53ce3efa091e6a46980bb716301891e6d65c420b2c25481f5f1fc0ec3e921fa1ec0b33e65a07ea284e90799149edd33ace9e67e83806405f98028558b45a5dcf6e411ac1d7ba070c2688533f8337332f5c7c11b1bd46704b7f2937d4683e509ca40cfb97502eda04b03a777f36dc9be61cca125223359ebb167562b64715f8aada6ee9f0219df0da093993ee43f49f3e33f6cb6541c6393dca4ac240893f1c0a250490f784d138814a085ae2d7b32dc0f0da002ea5033910b035e01f5ae12ff3105010e13a5a33c0ad4a00c39c1e39b90b4afab7648dd547f77b8f9d4c6d9e0c63e34ebf4c149c948edafa0e56b7c7c4656dd0b9f0919e09d6da771d38c453af4c0f0d6544f390fd2a543f7a081cca9739d3140249d6ae461371ff7b465883352d81bc757ca982f52d524c1dba0d3dbf7dcc484d241e77ee2be684b262f614f871a8c9d6598430a2134973782e0a09917ddd6820b6c66429eba999f5030141508a439dea8393b098035dbd283c287a0690b4d39eff7648da540434688e23bed68fe43f3711a9bc7dac7c15626fe1b7ba0c8af8672c865cd5af89c4a6b9e55b87f1dcf1ee0f76560a7d1f3c04daab60e4e80f90211a043beb9ae278028ab0e6ae1dd97bfc1adc7da5d5b35418cde1372ed15dc60d844a0969897f77040974812fdc243499998d5a2f808b010e3e743fff5bb1cf06701b7a072a62f95c81d3849bc02102bcb66b5be775ad3b68cae7967451e6a13c48b6c43a0488199752a3a18aaaaa52b07d5a306826c4ccb2afe3cb30058de3e361dee74cfa0a63fb5ff17b1ca7f9c095cd9a888f4fd493a3379cdc2a0cfb49353c854923fc7a0ce7a2593ac4b8c89ad4c5fde8940d9695e969cfe6eb6a614954a48bcfd715843a0cb8b4d0264778a2ab04b96777ffe78a5ee62483a87446fceccb37813cda25b60a008fac15554b1c384ad91aa696e7e5e5454dc0c0fa343bb26b48a4f34ec95f785a0f1811154dd01ffd9f43443acd407e0beee53bbd03f40f63b7d993681182f0289a0a620126c5db0919a29b4b27c728dc42d2d63015849527be64acd0062b575c0eea088d3cde1a49a0ac95f076d1e15b3fde9cefd0f7e308f53b3aa466eb0385aec50a07f99a989d621bd1b59fa51d109f6413c9cb7f8ccd704dbf13cfb27bebec8f1b1a04321111d914057fe87d18e8c6f4128c6c7778fa2b73d435f0b2562c5910361a2a07ee88a697a560dc7023a840f16df54c599dc345e787927bf6628963e782a6847a078d58eb776d8d9dd6dbdbdd830b0350bd0427b15678ef457da5d41ec2cca708ca050e0c4585785b9c800e24c4c4e00599d7e5c4e6d8f3363979ab6c49ed514f12680f90211a011ff0a2d404fd7ed97509ebaa806f2a5ba09c5cde5ff596903c4313783487509a014931c578b05f5948939281aa31d2bc8b05b01c6932c45bf7a70972a430575c2a07272592f567daa667135799961e9eef529a6cd754395e39694d9452ae24a8797a092b17ad714173ec4787f0b3b9d2dfa96680861e093b5121441ffcde64183d074a06db41a6efb6f94c7d185f76deb8bb00468715bf6828fb63db31b880a6050c54da07ce695737ab0d4bf9003a06ce83b11e75d81fbeb47c013b41f9c2e00a97cb87aa0dfe63771f833e98a5aeff54d9dd5a8dcfd89ca43c23644b18ec8e29ab8ccc287a0a327c817dc8a8ea3a5d3ca3cb55169777a1bfa30fe9f0df842eb3978dbd6737ba053683114bdaed7819b30ab8baec1fb9a2a96fee4dabc72f319cec9869da3b0b0a04d98297a896312d18da40240ed9a527f4c01c73edd3ea1f7c28338d1d863d97ca070451b5f2a402b497659eb18e648ac46f39c0068cc91436eb0b082b1d06dd63da066e866f800200512b0d3e534c547f4d2012429152cc9693bf1553cc22361627ba003fc4e648aafdadd7a9fa7cb534103f08dc699413ecda22bda46898bfb792429a0b46a167c66b50c74227d03a68971e124fdd011d6c90f5a08f6fe30ae34de603ca0a7ced66271235bc27b154f37bee6d9a1366cd253176c96de707d124fcc593c35a0f4f09b104a86cefc5c282d393b415e6c224eb8a463386448ebebfad9f9f53c9680f90211a05f93540f4317a4c6d8b73556a7ffdab6fcf0aa36af84b8c4bd2a3e7114e2da4ea05dd8c13b1b83485911f5e1185669f7d5559c260193a72e52597a3e80736c248ca03d50a67e8ec93696c35865d9f03814e95406c8d04e5decc320b9a24e5beee1baa0a928e2ea8773ba69dde5344d69069b237667dbaaa69e86133d4e444e432799b1a0ebb2cbf0c3314ddf681f21a29fa17b320094684ba35e725bc36bbc407821cfa3a0762aeb8161d2b1b8a5ee51d1ede36f51cc2dad7e0c4d0ff097b89c831aff8c35a0957a8eaaac924688482d21a95b7a7f01889ab39a7a50d58efaaffa9e486ae071a046c10b0c15aa83973ea4b108f50bad2638941550fce7c9308c8b968abee271f8a08a831384faa68f9caa047a6200464e11cfe5f9f700a5ed9435e5241d9d2a501ca020630d0f41d1f38c61fc8d3fc6170f6f11fc52ade454930a3b5e4f4491b47467a04539a99793f29484fdbd39b606f27265499acb3c24461f48858655f07166f0dfa05fd40548cfae17d12e103db98572f22cdc8dd3ec670be570727a7ff68f6bce9fa032efe866f058f79ef06de75f682e10773576eb9fca3f950fda96ea9926784685a05c170d685d29417781f678b746174c7500e7c228b4bd71bcfe9f5421742a0b67a0c3fb71b77522f06c4a4e4cb7029e7faeb747b8e446460586ea0d5e9abae68cd9a03f2294bf8bea287c7afafde4b39aaa56716230ef425ece688f6a78fcadf5f49e80f9013180a0c2cb770a3d18eb1214a782cc81b79a7fd772716c2d050ef66011095c3774e8f7a08fc7d7da06fba7ffa69b095aae41147e3a55b89644682057cedab705ba7aefd5a05975b434f69398107a4d1729f8f56e75247df09c65b1a750797818607bf118df80a026cea4c13260b2a1dd74bb6fcc7cc36162d2856ce691a36165c633ba68f7b783a0f7b0c667509a4ce937c487b45bc53c0700543daf4f8c127fbe475b4e1084d2328080a0454eca3fcc32afd4c4000ccbb47732bbce342b1a9d374fb5872162f2c873625fa0b3e6c44579a731cc730a5472e83c6098fa2943e5b2c72f4475f0afea76848a87a03b8c951788b8c93366aedbf88f6c1ca6085cd0249025ce542f19294b40bb92f180a0a10cfa51ae290afebd64a5b530db7088fa0b02f22ce9b0838135b422b885dee5808080e482000ea07b2632b8b97e159d88f112a8dd9d44df2f3c4502e0c79a29297ea7f61f41f311f851a030590b16841225b9590cdc95b19176201d442ca0b931c6e4314d20a1c772ea9ba052e8f9f247cd159c65b304863d444087f6a60d7dbec3a0e4fa09f007b5a1c64f808080808080808080808080808080f86c9c20120c458c4c09a9448628f84e81161b308d5c4041a3d3a1ea329d0eb84df84b0487400e8b4f1c9c00a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47022440bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e22442465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c8162244295e26495cef6f69dfa69911d9d8e4f3bbadb89b977cf58294f7239d515e15b24cfeb82494056cf691eaf729b165f32c9757c429dba5051155903067e56ebe3698678e9122442d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab022443f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a224461dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d25224469c77a677c40c7fbea129d4b171a39b7a8ddabfab2317f59d86abfaf690850223d90e9e7593d91a29331dfc2f84d5adecc75fc39ecab4632c1b4400a3dd1e1298835bcca224472b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a5122447ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e22448b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d788694852244a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b7412244b218c5d6af1f979ac42bc68d98a5a0d796c6ab01b659ad0fbd9f515893fdd740b29ba0772dbde9b4635921dd91bd2963a0fc855e31f6338f45b211c4e9dedb7f2eb09de72244b4dd66d7c2c7e57f628210187192fb89d4b99dd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002244be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cd2244cc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a4192244d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce7392244e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d212244e9ae3261a475a27bb1028f140bc2a7c843318afd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002244ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c1921832244ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5b2244ef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd0756e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd02a440bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e2a4412d810c13e42811e9907c02e02d1fad46cfa18bab679cbab0276ac30ff5f198e5e1dedf6b84959129f70fe7a07fcdf13444ba45b5dbaa7b1f650adf8b0acbecd04e2675b2a442465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c8162a442d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab02a443f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a2a4461dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d252a4470f657164e5b75689b64b7fd1fa275f334f28e1896a26afa1295da81418593bd12814463d9f6e45c36a0e47eb4cd3e5b6af29c41e2a3a5636430155a466e216585af3ba72a4472b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a512a447ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e2a448b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d788694852a44a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b7412a44b4dd66d7c2c7e57f628210187192fb89d4b99dd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a44be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cd2a44cc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a4192a44d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce7392a44d93dbfb27e027f5e9e6da52b9e1c413ce35adc11b313f9cba57c63a84edb4079140e6dbd7829e5023c9532fce57e9fe602400a2953f4bf7dab66cca16e97be95d4de70442a44e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d212a44e9ae3261a475a27bb1028f140bc2a7c843318afd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a44ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c1921832a44ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5b2a44ef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd0756e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd0").to_vec(); - let height = 32160203; - let trusted_height = 32160202; - let trusted_current_validator_hash = - hex!("abe3670d5b312d3dd78123a31673e12413573eac5cada972eefb608edae91cac"); - let trusted_previous_validator_hash = - hex!("dc895253030c1833d95cfaa05c9aac223222099bc4b86ab99eeab6021ba64a71"); - let new_current_validator_hash = trusted_current_validator_hash; - let new_previous_validator_hash = trusted_previous_validator_hash; + #[rstest] + #[case::localnet(localnet())] + fn test_success_update_state_non_epoch(#[case] hp: Box) { + let input = hp.success_update_client_non_epoch_input(); + let new_current_validators_hash = input.trusted_current_validators_hash; + let new_previous_validators_hash = input.trusted_previous_validators_hash; do_test_success_update_state( - header, - height, - trusted_height, - trusted_current_validator_hash, - trusted_previous_validator_hash, - new_current_validator_hash, - new_previous_validator_hash, - 56, + input.header, + input.trusted_height, + input.trusted_current_validators_hash, + input.trusted_previous_validators_hash, + new_current_validators_hash, + new_previous_validators_hash, + input.expected_storage_root, + hp.ibc_store_address(), + hp.network(), ) } #[allow(clippy::too_many_arguments)] fn do_test_success_update_state( header: Vec, - height: u64, trusted_height: u64, trusted_current_validator_hash: Hash, trusted_previous_validator_hash: Hash, new_current_validator_hash: Hash, new_previous_validator_hash: Hash, - chain_id: u64, + expected_storage_root: Hash, + ibc_store_address: Address, + chain_id: ChainId, ) { let any: Any = header.try_into().unwrap(); let header = Header::try_from(any.clone()).unwrap(); - let client = ParliaLightClient::default(); let client_id = ClientId::new(&client.client_type(), 1).unwrap(); let mut mock_consensus_state = BTreeMap::new(); @@ -687,9 +651,9 @@ mod test { }; mock_consensus_state.insert(Height::new(0, trusted_height), trusted_cs.clone()); let cs = ClientState { - chain_id: ChainId::new(chain_id), - ibc_store_address: hex!("151f3951FA218cac426edFe078fA9e5C6dceA500"), - latest_height: Height::new(0, height), + chain_id, + ibc_store_address, + latest_height: Height::new(0, trusted_height), ..Default::default() }; let ctx = MockClientReader { @@ -707,10 +671,7 @@ mod test { ConsensusState::try_from(data.new_any_consensus_state).unwrap(); assert_eq!(data.height, header.height()); assert_eq!(new_client_state.latest_height, header.height()); - assert_eq!( - new_consensus_state.state_root, - hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - ); + assert_eq!(new_consensus_state.state_root, expected_storage_root); assert_eq!(new_consensus_state.timestamp, header.timestamp().unwrap()); assert_eq!( new_consensus_state.current_validators_hash, @@ -747,49 +708,92 @@ mod test { }; } - #[test] - fn test_error_update_state() { - let header= hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212fd460a9e060a9b06f90318a0aeb34c70bba2db766857340f3b9a391b5332c5be7dfc6fd45117d95cf32bda85a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479472b61c6014342d914470ec7ac2975be345796c2ba00000000000000000000000000000000000000000000000000000000000000000a09327a61481b2408f2a2d3cd4c1956259215eedd9f5f4cfe53ef0df89e80f335da0b35856be0503b120103115c6bf48ffd750e2e83880676f70dc34d9a50e64c247b9010086260674d1c0d73c1d5439558051687683845288bc1a18743c2f814631882c40ee4cb9a2e88cc19c00d0ffba0a9e52229b8ec1199402712450c0e129dd2e34e1e76229f4ff416ca91999c02be1244ebe72319828856ee26620067491c7350a60c8ec82234aeeada54d47cbb2d56cad888acace4fa8ad4d781a086a10834a41c1ced08b15a31d0fd6d49a74ac4c9859de90678ec168b1447b2ad14aca95820d302bdf881553828a51931897e70e823cdb756ad6a59e860337202804322910cae3e53a565e4a00acd75e272289417757352275514595e7b09de390550f72b0fca83118a79791f57909630507827a144d4015e48d3be9ba43ca3b6684307a210ded028401eab9f784084fe2c68401193c0f84651682deb90118d88301020b846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5831defffb860ae89c1a42abb17a167fd49be92d22898e1a449743966cc36a8813508a5e5f8c180e0a2713d5cc8d748acd0fdb95c3a9d0134fec56824b3b1901378823ffd3e98d36bd1574329805cdd96499704ce21dfee1c3b35e744a4dd5f2e8c811a939143f84c8401eab9f5a04faca5268b7a0425eccecac9a27a75e9e4e6abeaf018eed562ef01a8ff8f6cd78401eab9f6a0aeb34c70bba2db766857340f3b9a391b5332c5be7dfc6fd45117d95cf32bda85804ef67727f6a4a908a26a1229538a5b7f90bec3e2e6b8fc5420045b8c5520343932847f59933c3a400d088d5fe9f5fde2ae5809ac8b3a11de33e7818c8fec422b00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a0c2bb1d712ce142a2ef22b975ed83416ea31f4545b297765e7456d0c0ebeb9f28a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347947ae2f5b9e386cd1b50a4550696d957cb4900f03aa06afbbdd36cb61f3d2a651bc6218ef4b7fb7ad2367195105a67e952189dbc3188a03709615ddca48112289d87be4f8083e7067d4d0898f983132558e12a897c1d87a08227455c29c40f1bbbe4792e2b9814d98cb622d862f5aeca8373dfae7969e8deb90100527986d63768151ac9100068b058b15181120286f3710c10315231ea512011068a40b85371d9920143217125061e0022a922251aa54b564851d018b5322e06e84e0284800b610c5011b4488daa630abc30d8092409742d4185661a5480143d20483ab8b35a2b61e64c53181051490f3b18818f5d814c05a453e7ac982a08455010e2e4213709480d8ac067480a4c09b8066c8cc5310e01084b99ce6078f20c6fb3d100f256e88197218058454b8ec711314200612a0a4325b022a66824eb28cee540cd62006443c712205a0d423fd94d23d1af94d00215dd6512d4d60064e57408d5a043c0e8c3ca231402ee4820e524710004104738446ebd5b151e4c614844028401eab9f884085832a783cfa37b84651682e1b90118d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a2f8b5831defffb860a1f5946901ac7f9e875f2fdcb906700be782d4720fda4bf4c5e9680b62608c09c051723f6eb08edca330815bf3836987093575166c87a59e64cc7798737d2c4d3eee7b080d888a5454e689a3df1a6e1d2b655dec52ae3f8c444b90a93ea478b6f84c8401eab9f6a0aeb34c70bba2db766857340f3b9a391b5332c5be7dfc6fd45117d95cf32bda858401eab9f7a0c2bb1d712ce142a2ef22b975ed83416ea31f4545b297765e7456d0c0ebeb9f28804f1bcd3484aea92f5ab7772ec713cb6f94b092c251b5ae134bd178111aaf5ce95b23b86e4965e9578cfd6240ec8b7a6effa75aecaa6326cfa42aceec2b69a59200a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9e060a9b06f90318a05c1a4ac59fa493c7add0898f753bd3b6eca7717d0424cc3660d9908233989079a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a0f82ea8b35f53773563a8ecb3287113bbbd5efaedcd09834667e32212ff288fbea0689b79ba82934bb61ee8f64af6f980d9bf164419dc9329f9d62a33b621e1a5eea06f8a552cbb9e52bff118baa395c75251a3b582c0b6dcc93bfc4fa0a15cca1dd5b90100cfa64722a69e3dbe2e9978dcb71e5cff8f31e4f436e949285fa0ab4f3b89ad5fa7b1d411f036b680cd1a337a4512e71b9f1f1eff1192aa4066cd5a1e743c2a82bc41ead1af65dc218d7ec42ca585c7bf699f91a4f354da97efacb534e051bc91dc3ddb35cf07d9cc544f9daf23632d192c3fdf498a81ed387a70b615fe8728d7d5ead0ae3a2100759197b4115f766988213e2607ff25195b2d5526c68b684cf5bf910071e2afab080fbc1dce2f9e9c9a45e3035d3ddbfc2962543e22eaeb3c60d0acfe2667a46d6e10d398b91c33d4e06671fb9a959f8f3d4511d5febdecbef813f2c752f3f3ddb8893758fa30ab83f972b24c1843b34ec81e4fcf5ef8ad6c4a028401eab9f98408583b00840129f24984651682e4b90118d883010209846765746888676f312e32302e36856c696e7578000000b19df4a2f8b5831defffb860b0f58980edb50dd10c56c83443f5ebd140d430a422bfa1168da234e15187977283647b7ec30a3443a2d5bc5c705ea19d193782aca1a29a5adf2e8378e2c86498185700253f885dbf3c58d05a785f9bb3dcc914fbbbcd4addae9aaf8a3eea0575f84c8401eab9f7a0c2bb1d712ce142a2ef22b975ed83416ea31f4545b297765e7456d0c0ebeb9f288401eab9f8a05c1a4ac59fa493c7add0898f753bd3b6eca7717d0424cc3660d9908233989079809d9d51ff8ea924fcbb62f90bd0a6185457a3a5c6e7d074acb2d35373e02ab466039d3d23c795be05eca2773251b0bb4ac7dc25e247d3f295ffb6421e6b65fd5b01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080120510f6f3aa0f1a951df90e92f90211a05760c478b528201548b880f9df75f669b35285dfe4bce3a2245b6fdace23806ea06702ed5328fc88ae32788582fdce6087c3772e9f2872be07dddfd72bce23e6e6a076fecf1768f2efca0493b32434dc758cb1804a9eba8479ecc244490d02016850a05fc46706b33918b46e21e0552215669313eb6fee038e8662a364d450f20b765ea02162336e1f97ea3aaaf26e5482e752e3bc335f146b08a4ec067bb2f6b66ad4eba0f9c52bc52d2bff446b57580612ff3d5e5ce63fe38ae9a6c286068fe6d8dd69e1a0f2ffb55c6c86989060e530e9300716eb81b402ee6e54d6845e40f256cc5a30a8a040307a80bb9b2672c1ddf9e009377bf6f792ccb6471975a7efbae167310f32dda0ed0a7cf42511cdf4c79e1cf995074202e10b148e9d8cc9ff459ea63bd456c292a0d8642102cd0c903c286313b4da9fc2d576f819d24c5dc9decf7a72d6c5f3a6f5a0a72af8ac881122fe9e28643d845ec0bdb82e7c6844c4e90d1375b3b6d00b2e83a027e16ad7e44adc72b9f25459e50d59ebdfc2df5210a317e9af7e6953001b06d4a0e2c69d81c457b2499b10a65b4764ea149ce06c38e20a1b81034c86c1072ed008a000f2f7a39a9572c5eaf08e46f20a46f2b3b9f0dba44940cbb3b717e8cb72cd0ea053da4d2d3e34749b27aa7867bc4eaa05c33e5ebb914eb7a2eda4337b302fa43aa094da8ed2b23a83012b966d1361235fc24cb33a0886be41d9ee19862cb313094580f90211a0a2128874d2823da6bd7cdf67438effc0e407274501327d2405e25687585eb70ba05b0986965e23b96ad60c8af08434733c40efe29db0c993d7ba9bc4ffa1483ba8a0f43d30c11169496786df08702b0080269f67dec4afc589a629f481b16d19832ba04a12b6f2493e006b66605e1d00af7f6eb3f6c733dd84cf40ddf5f89267e8e7aba064e170ac6680f6cdf1e42faba258367fcf0393b6b2ccdc896d90acbd23ab5465a070771a010394851774d88d286b57bdf9faf9d9356a2240128eb9de145ec2edfba02dc8752dafe069b464c36b8509826d726c1f131f205a49fe8788659122203620a0f63f4e9a984f664b13b67dfe922fc3a560efce6720b9172614e11965dfa3b711a05afa9694c979c6904d88cf2f248a755f41b78a44ecfd7861bbf11ab617528723a0b5d0e96e1a30c464bcbadf2fb1e6587f30c26e611912bc71298309869803e01ba0bb30f6dd3be410db17d680911856ad5068698256462beda07b6fa0ecb2c795d6a016d61ebc2df2ae26c81a9e42e21e690835a3855cd5fb8b080914b29e61b0cba9a07f3f00a25937d9fa7f5fab4e72c39e7c61e2744c3a7f98489ab4d1b2e7caedf3a0cb308105ad0e53f8295d98d64926f0e932459a9690b5a54bcf5557985cf4e401a0e5fd124381dc44dcd9fc74bdc6d9e73eed51c739aad2270730c146a80ae4f1f2a02bdd929c52fb5bbcb95162cce765015a272ef934c1c0c7ed38c8ca2c0bef5ad280f90211a0e6d6c23fa1734c2f5d243a3cfb0f39cd02cfbfdb4bc3c8f431aed32fcd2854dda03869abaa6f82c34c1aba13cfe0b7ad104312b8ca918060c181dd406c8a99260ca0f753573922dd3666bd8c5dbd5b4ce6de8a8f0800188c034d383d8916a53ce3efa087492846af03fde43add538ba9a0cd3a58dda4f92af41fa5ec85c724b3569952a0251aab0f729960016c67c4450afcea003fe27516ae12a4aacbba88c2218d609aa00773c02f14993b861c986adb86c48e2b964b04fc93b7c14e0adf236ba48fc3c3a0895fe437ecebfb9a688f7de6f3e9ef5118168fc60d9eee552eb504d64d301f6fa098e233266cb2949de7efbc5249a002cd0e347ee19307a53498a6d46ae5dd5e5ea0668cead9c0b63d7ebcb34a1a5864a894baac5fc4a85fae89ff6301645b1a2c5aa0001d500e083c7b36f84d6d19af62df79986281f6c826e47f44d7b97c3d106af4a0607867cd831b1cac0eb801706ed0a6c762746c07b8ee12870445c526da6058a3a0c82d3b93fbfab9bb7d75a7eae35fb9ab46558857867d24d65de62e93befd63bda0a39ffe983c540e96c66156dc256c27ab556267c1169629ebecf09c11dca8ad7fa09917ddd6820b6c66429eba999f5030141508a439dea8393b098035dbd283c287a04d959bbbe8ea6b950a3c865aca329123dac37debff5ea2531c8a25af9e09b1eea03d184ecdda0c942db6d34a492675d82093b1bdea5eb088d69e6502fff16bc71980f90211a043beb9ae278028ab0e6ae1dd97bfc1adc7da5d5b35418cde1372ed15dc60d844a0969897f77040974812fdc243499998d5a2f808b010e3e743fff5bb1cf06701b7a072a62f95c81d3849bc02102bcb66b5be775ad3b68cae7967451e6a13c48b6c43a0488199752a3a18aaaaa52b07d5a306826c4ccb2afe3cb30058de3e361dee74cfa0a63fb5ff17b1ca7f9c095cd9a888f4fd493a3379cdc2a0cfb49353c854923fc7a0ce7a2593ac4b8c89ad4c5fde8940d9695e969cfe6eb6a614954a48bcfd715843a0cb8b4d0264778a2ab04b96777ffe78a5ee62483a87446fceccb37813cda25b60a008fac15554b1c384ad91aa696e7e5e5454dc0c0fa343bb26b48a4f34ec95f785a0f1811154dd01ffd9f43443acd407e0beee53bbd03f40f63b7d993681182f0289a0a620126c5db0919a29b4b27c728dc42d2d63015849527be64acd0062b575c0eea088d3cde1a49a0ac95f076d1e15b3fde9cefd0f7e308f53b3aa466eb0385aec50a07f99a989d621bd1b59fa51d109f6413c9cb7f8ccd704dbf13cfb27bebec8f1b1a04321111d914057fe87d18e8c6f4128c6c7778fa2b73d435f0b2562c5910361a2a07ee88a697a560dc7023a840f16df54c599dc345e787927bf6628963e782a6847a078d58eb776d8d9dd6dbdbdd830b0350bd0427b15678ef457da5d41ec2cca708ca050e0c4585785b9c800e24c4c4e00599d7e5c4e6d8f3363979ab6c49ed514f12680f90211a011ff0a2d404fd7ed97509ebaa806f2a5ba09c5cde5ff596903c4313783487509a014931c578b05f5948939281aa31d2bc8b05b01c6932c45bf7a70972a430575c2a07272592f567daa667135799961e9eef529a6cd754395e39694d9452ae24a8797a092b17ad714173ec4787f0b3b9d2dfa96680861e093b5121441ffcde64183d074a06db41a6efb6f94c7d185f76deb8bb00468715bf6828fb63db31b880a6050c54da07ce695737ab0d4bf9003a06ce83b11e75d81fbeb47c013b41f9c2e00a97cb87aa0dfe63771f833e98a5aeff54d9dd5a8dcfd89ca43c23644b18ec8e29ab8ccc287a0a327c817dc8a8ea3a5d3ca3cb55169777a1bfa30fe9f0df842eb3978dbd6737ba053683114bdaed7819b30ab8baec1fb9a2a96fee4dabc72f319cec9869da3b0b0a04d98297a896312d18da40240ed9a527f4c01c73edd3ea1f7c28338d1d863d97ca070451b5f2a402b497659eb18e648ac46f39c0068cc91436eb0b082b1d06dd63da066e866f800200512b0d3e534c547f4d2012429152cc9693bf1553cc22361627ba003fc4e648aafdadd7a9fa7cb534103f08dc699413ecda22bda46898bfb792429a0b46a167c66b50c74227d03a68971e124fdd011d6c90f5a08f6fe30ae34de603ca0a7ced66271235bc27b154f37bee6d9a1366cd253176c96de707d124fcc593c35a0f4f09b104a86cefc5c282d393b415e6c224eb8a463386448ebebfad9f9f53c9680f90211a05f93540f4317a4c6d8b73556a7ffdab6fcf0aa36af84b8c4bd2a3e7114e2da4ea05dd8c13b1b83485911f5e1185669f7d5559c260193a72e52597a3e80736c248ca03d50a67e8ec93696c35865d9f03814e95406c8d04e5decc320b9a24e5beee1baa0a928e2ea8773ba69dde5344d69069b237667dbaaa69e86133d4e444e432799b1a0ebb2cbf0c3314ddf681f21a29fa17b320094684ba35e725bc36bbc407821cfa3a0762aeb8161d2b1b8a5ee51d1ede36f51cc2dad7e0c4d0ff097b89c831aff8c35a0957a8eaaac924688482d21a95b7a7f01889ab39a7a50d58efaaffa9e486ae071a046c10b0c15aa83973ea4b108f50bad2638941550fce7c9308c8b968abee271f8a08a831384faa68f9caa047a6200464e11cfe5f9f700a5ed9435e5241d9d2a501ca020630d0f41d1f38c61fc8d3fc6170f6f11fc52ade454930a3b5e4f4491b47467a04539a99793f29484fdbd39b606f27265499acb3c24461f48858655f07166f0dfa05fd40548cfae17d12e103db98572f22cdc8dd3ec670be570727a7ff68f6bce9fa032efe866f058f79ef06de75f682e10773576eb9fca3f950fda96ea9926784685a05c170d685d29417781f678b746174c7500e7c228b4bd71bcfe9f5421742a0b67a0c3fb71b77522f06c4a4e4cb7029e7faeb747b8e446460586ea0d5e9abae68cd9a03f2294bf8bea287c7afafde4b39aaa56716230ef425ece688f6a78fcadf5f49e80f9013180a0c2cb770a3d18eb1214a782cc81b79a7fd772716c2d050ef66011095c3774e8f7a08fc7d7da06fba7ffa69b095aae41147e3a55b89644682057cedab705ba7aefd5a05975b434f69398107a4d1729f8f56e75247df09c65b1a750797818607bf118df80a026cea4c13260b2a1dd74bb6fcc7cc36162d2856ce691a36165c633ba68f7b783a0f7b0c667509a4ce937c487b45bc53c0700543daf4f8c127fbe475b4e1084d2328080a0454eca3fcc32afd4c4000ccbb47732bbce342b1a9d374fb5872162f2c873625fa0b3e6c44579a731cc730a5472e83c6098fa2943e5b2c72f4475f0afea76848a87a03b8c951788b8c93366aedbf88f6c1ca6085cd0249025ce542f19294b40bb92f180a0a10cfa51ae290afebd64a5b530db7088fa0b02f22ce9b0838135b422b885dee5808080e482000ea07b2632b8b97e159d88f112a8dd9d44df2f3c4502e0c79a29297ea7f61f41f311f851a030590b16841225b9590cdc95b19176201d442ca0b931c6e4314d20a1c772ea9ba052e8f9f247cd159c65b304863d444087f6a60d7dbec3a0e4fa09f007b5a1c64f808080808080808080808080808080f86c9c20120c458c4c09a9448628f84e81161b308d5c4041a3d3a1ea329d0eb84df84b0487400e8b4f1c9c00a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47022440bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e22442465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c8162244295e26495cef6f69dfa69911d9d8e4f3bbadb89b977cf58294f7239d515e15b24cfeb82494056cf691eaf729b165f32c9757c429dba5051155903067e56ebe3698678e9122442d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab022443f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a224461dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d25224469c77a677c40c7fbea129d4b171a39b7a8ddabfab2317f59d86abfaf690850223d90e9e7593d91a29331dfc2f84d5adecc75fc39ecab4632c1b4400a3dd1e1298835bcca224472b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a5122447ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e22448b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d788694852244a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b7412244b218c5d6af1f979ac42bc68d98a5a0d796c6ab01b659ad0fbd9f515893fdd740b29ba0772dbde9b4635921dd91bd2963a0fc855e31f6338f45b211c4e9dedb7f2eb09de72244b4dd66d7c2c7e57f628210187192fb89d4b99dd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002244be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cd2244cc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a4192244d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce7392244e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d212244e9ae3261a475a27bb1028f140bc2a7c843318afd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002244ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c1921832244ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5b2244ef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd0756e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd02a440bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e2a4412d810c13e42811e9907c02e02d1fad46cfa18bab679cbab0276ac30ff5f198e5e1dedf6b84959129f70fe7a07fcdf13444ba45b5dbaa7b1f650adf8b0acbecd04e2675b2a442465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c8162a442d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab02a443f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a2a4461dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d252a4470f657164e5b75689b64b7fd1fa275f334f28e1896a26afa1295da81418593bd12814463d9f6e45c36a0e47eb4cd3e5b6af29c41e2a3a5636430155a466e216585af3ba72a4472b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a512a447ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e2a448b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d788694852a44a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b7412a44b4dd66d7c2c7e57f628210187192fb89d4b99dd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a44be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cd2a44cc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a4192a44d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce7392a44d93dbfb27e027f5e9e6da52b9e1c413ce35adc11b313f9cba57c63a84edb4079140e6dbd7829e5023c9532fce57e9fe602400a2953f4bf7dab66cca16e97be95d4de70442a44e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d212a44e9ae3261a475a27bb1028f140bc2a7c843318afd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a44ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c1921832a44ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5b2a44ef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd0756e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd0").to_vec(); + #[rstest] + #[case::localnet(localnet())] + fn test_success_update_state_continuous(#[case] hp: Box) { + let client = ParliaLightClient::default(); + let client_id = ClientId::new(&client.client_type(), 1).unwrap(); + let header_groups = hp.success_update_client_continuous_input(); + + for headers in header_groups { + let any: Any = headers.first().unwrap().clone().try_into().unwrap(); + let first = Header::try_from(any.clone()).unwrap(); + if !first.eth_header().target.is_epoch() { + panic!("first header of each group must be epoch"); + } + // create client + let mut mock_consensus_state = BTreeMap::new(); + let trusted_cs = ConsensusState { + current_validators_hash: first.previous_epoch_validators_hash(), + ..Default::default() + }; + mock_consensus_state.insert(first.trusted_height(), trusted_cs.clone()); + let mut cs = ClientState { + chain_id: hp.network(), + ibc_store_address: hp.ibc_store_address(), + latest_height: first.trusted_height(), + ..Default::default() + }; + + let mut ctx = MockClientReader { + client_state: Some(cs.clone()), + consensus_state: mock_consensus_state, + }; + for header in &headers { + let any: Any = header.clone().try_into().unwrap(); + let header = Header::try_from(any.clone()).unwrap(); + let result = client.update_client(&ctx, client_id.clone(), any).unwrap(); + match result { + UpdateClientResult::UpdateState(state) => { + ctx.consensus_state.insert( + header.height(), + state.new_any_consensus_state.try_into().unwrap(), + ); + cs.latest_height = state.height; + } + _ => unreachable!("invalid update_client result"), + } + } + + let any: Any = headers.last().unwrap().clone().try_into().unwrap(); + let last = Header::try_from(any.clone()).unwrap(); + assert_eq!(cs.latest_height, last.height()); + } + } + + #[rstest] + #[case::localnet(localnet())] + fn test_error_update_state(#[case] hp: Box) { + let input = hp.success_update_client_epoch_input(); + let header = input.header; let any: Any = header.try_into().unwrap(); let client = ParliaLightClient::default(); let client_id = ClientId::new(&client.client_type(), 1).unwrap(); let mut mock_consensus_state = BTreeMap::new(); - let trusted_cs = ConsensusState { - current_validators_hash: hex!( - "abe3670d5b312d3dd78123a31673e12413573eac5cada972eefb608edae91cac" - ), - previous_validators_hash: hex!( - "dc895253030c1833d95cfaa05c9aac223222099bc4b86ab99eeab6021ba64a71" - ), - ..Default::default() - }; - mock_consensus_state.insert(Height::new(0, 32160246), trusted_cs); + + // fail: check_header_and_update_state (invalid validator hash) + mock_consensus_state.insert( + Height::new(0, input.trusted_height), + ConsensusState { + current_validators_hash: [0u8; 32], + previous_validators_hash: input.trusted_previous_validators_hash, + ..Default::default() + }, + ); let ctx = MockClientReader { client_state: Some(ClientState { - chain_id: ChainId::new(56), - ibc_store_address: hex!("151f3951FA218cac426edFe078fA9e5C6dceA500"), - latest_height: Height::new(0, 32160247), + chain_id: hp.network(), + ibc_store_address: hp.ibc_store_address(), + latest_height: Height::new(0, input.trusted_height), ..Default::default() }), consensus_state: mock_consensus_state.clone(), }; - - // fail: check_header_and_update_state let err = client .update_client(&ctx, client_id.clone(), any.clone()) .unwrap_err(); - assert!( - format!("{:?}", err).contains("UnexpectedHeaderRelation: 32160247 32160248"), - "{}", - err - ); - // assert testdata validity - let de_header: Header = any.clone().try_into().unwrap(); - assert_ne!( - de_header.eth_header().target.hash, - de_header.eth_header().all[1].parent_hash.as_slice() - ); + assert_err(err, "UnexpectedUntrustedValidatorsHashInEpoch"); // fail: client_frozen let ctx = MockClientReader { @@ -802,11 +806,7 @@ mod test { let err = client .update_client(&ctx, client_id.clone(), any.clone()) .unwrap_err(); - assert!( - format!("{:?}", err).contains("ClientFrozen: xx-parlia-1"), - "{}", - err - ); + assert_err(err, "ClientFrozen: xx-parlia-1"); // fail: client state not found let ctx = MockClientReader { @@ -816,28 +816,50 @@ mod test { let err = client .update_client(&ctx, client_id.clone(), any.clone()) .unwrap_err(); - assert!( - format!("{:?}", err).contains("client_state not found: client_id=xx-parlia-1"), - "{}", - err - ); + assert_err(err, "client_state not found: client_id=xx-parlia-1"); // fail: consensus state not found let ctx = MockClientReader { client_state: Some(ClientState { - chain_id: ChainId::new(56), - ibc_store_address: hex!("151f3951FA218cac426edFe078fA9e5C6dceA500"), - latest_height: Height::new(0, 32160247), + chain_id: hp.network(), + ibc_store_address: hp.ibc_store_address(), + latest_height: Height::new(0, input.trusted_height), ..Default::default() }), consensus_state: BTreeMap::new(), }; let err = client.update_client(&ctx, client_id, any).unwrap_err(); - assert!( - format!("{:?}", err) - .contains("consensus_state not found: client_id=xx-parlia-1 height=0-32160246"), - "{}", - err + assert_err( + err, + &format!( + "consensus_state not found: client_id=xx-parlia-1 height=0-{}", + input.trusted_height + ), + ); + } + + #[rstest] + #[case::localnet(localnet())] + fn test_error_update_state_non_neighboring_epoch(#[case] hp: Box) { + let input = Any::try_from(hp.error_update_client_non_neighboring_epoch_input()).unwrap(); + let header = Header::try_from(input.clone()).unwrap(); + let trusted_height = header.trusted_height(); + + let client = ParliaLightClient::default(); + let client_id = ClientId::new(&client.client_type(), 1).unwrap(); + let mut mock_consensus_state = BTreeMap::new(); + mock_consensus_state.insert(trusted_height, ConsensusState::default()); + let ctx = MockClientReader { + client_state: Some(ClientState::default()), + consensus_state: mock_consensus_state, + }; + let err = client.update_client(&ctx, client_id, input).unwrap_err(); + assert_err( + err, + &format!( + "UnexpectedTrustedHeight: {}", + trusted_height.revision_height() + ), ); } @@ -882,8 +904,7 @@ mod test { false, ) .unwrap_err(); - let expected = format!("{:?}", err).contains("UnexpectedStateValue"); - assert!(expected, "{}", err); + assert_err(err, "UnexpectedStateValue"); let latest_height = new_height( proof_height.revision_number(), @@ -899,8 +920,7 @@ mod test { false, ) .unwrap_err(); - let expected = format!("{:?}", err).contains("UnexpectedProofHeight"); - assert!(expected, "{}", err); + assert_err(err, "UnexpectedProofHeight"); let err = do_test_verify_membership( path, @@ -961,19 +981,26 @@ mod test { // Detect misbehavior // Use blocks of two local nets with the same ChainID(=9999) and validator set. - let any = hex!("0a282f6962632e6c69676874636c69656e74732e7061726c69612e76312e4d69736265686176696f757212b1340a0b78782d7061726c69612d31128f1a0a90060a8d06f9030aa025ffb3920008fd0591adc665132f7296d4d3da213f27ad5f13c29bae6b53b150a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a03feedbe444fcdaeea389d10588435b9657b71aea384266ac09e15c0772ea6bc9a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028204a58402625a00808465122d33b90111d98301020b846765746889676f312e31392e3133856c696e75780000e904d98cf8ae07b8608ce4e95f382e2d06eb6c98641c574069f7c8cfdb482a4c58290f9f2ee86f6d4ce520d7bb6a6be1acd082c07a9d65b45f1334def3c66fc793003cf06f3fcea7ce055b34aa911f6ff7b9bf2eb083f3e7010a34e8c61aa70edd8ad630c82f3d4a8bf8488204a3a02d59fc7d664ae17504839bf6c49ca0e21fa794fe661c86e929a522bd4872d3458204a4a025ffb3920008fd0591adc665132f7296d4d3da213f27ad5f13c29bae6b53b1508022216e66d52050e392e6a6b86f677363e01be8deb6611cab76cada1bfd6c0b7048798c2376f52d8357d8aeb6e6c0109dd802675c849dff145dc3dd470fc7bce400a000000000000000000000000000000000000000000000000000000000000000008800000000000000000a90060a8d06f9030aa09432b9b136e91a12cea5e9cc363bc821e90da6c7b2d7f369533afa746ac21508a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a03feedbe444fcdaeea389d10588435b9657b71aea384266ac09e15c0772ea6bc9a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028204a68402625a00808465122d36b90111d98301020b846765746889676f312e31392e3133856c696e75780000e904d98cf8ae07b8608f21cd736cba2bf8c4af32f237f4851282c77b602f3e5ef48c48e16b36fae2f8a80bdb501d48c235b3409ec53340742919fbab1a54cde9da53886da4e7280a7c450714fbdd1dd5907a9f4990fb99e1badebba671d521d47f1cdd23ce3eec2e90f8488204a4a025ffb3920008fd0591adc665132f7296d4d3da213f27ad5f13c29bae6b53b1508204a5a09432b9b136e91a12cea5e9cc363bc821e90da6c7b2d7f369533afa746ac21508804b8debfb8d55a7f71547fd88e1c40eb0efe960d32d08601589e22a62bb0ebeb26b984bba8f736484ae789567e5d9563104126e78181a293d6ee504e9ad35725801a000000000000000000000000000000000000000000000000000000000000000008800000000000000000a90060a8d06f9030aa086efaa0d95f31de170d88687b07806f3bf271bf842b65f6dd76b326e1575e609a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a03feedbe444fcdaeea389d10588435b9657b71aea384266ac09e15c0772ea6bc9a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028204a78402625a00808465122d39b90111d98301020b846765746889676f312e31392e3133856c696e75780000e904d98cf8ae07b86094c8bc4a6ed9b43a592f7c7a035e27b119ff45ea9e7e6ab149136ab18f268499c6d6d920aab86608315093fffaa354cf0077173664aebe97ca185285e739559a01c96d04a30df92c23ce051b1700c8fabd41e1ac8db8229a3c08a067a60a4ee7f8488204a5a09432b9b136e91a12cea5e9cc363bc821e90da6c7b2d7f369533afa746ac215088204a6a086efaa0d95f31de170d88687b07806f3bf271bf842b65f6dd76b326e1575e6098085641457482587c8687b5e40069f915f48961cad6069305c278fb117d4661cd80c92987afd0b4e44e794945580feeedece4b1b68098b6134de8be2ed2245aa8b01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000120310a0091aaa04f90227f901d1a06ed7d26d8a14a9cd8aeb3f01960cae49b7e95dbd549fff6556694ea3ee3dc173a0c445c1e18313a154c9cfd1a1bdbf2fb6d7513227c59c5cfe4ed6b2f1585ea74ea06c664a574aeaa739d85b114d13a20a15330b02565910dfb142b6715b5742a562a0726016a81a8017e5825a30ad9481c2ea45a35601f9e17a25ef74fb2fcc093ecb80a019977eb86a7f4c991220db91b3be76de8c43b5f5ea5414ad2ae17d27226ff633a075d1dffd2abda435b74cfaccf176f5e0938c60d66068a44727add2ef2df1f3eea0c993119ba273a56742e6fa6f92bb58a0120a3b3d27200340be21bc37ae8fdce2a04f3e6cb5f42f4cfe12e8e586e820edf8460ca87b27b4823c129d986c127e4898a07def82f69a90079ffaeaa69f6fda2b28363547c376948939c06aa8206c51c022a0b84308f4cb54366a086a4fdd936c40ab7ba0429ca9b7a624a6db6c5ac35c0b9ca041feda5565ebddc0a30be2e0fef75fe61729344ec36395f2f1e60865cd434a58a01223a2c45e23b4266f6b786bb346c31ea0c18ac94135d2f5138cc2851f7bf44a80a00d690f6252aa5118f41dce0eb3fdd420419d6d73ef7d51559385cab56a0308e2a054529b9b4e918ca60d7d2c1f1c9104a1442f9dcee09012b637ec7bd7ec46702680f8518080808080808080a00f079d6471365442c66c0559bffebac0b429bc330e636338e9c5dac3bd3fbaf7808080a0e2ec5bfa0874d74ec0fdffc07602dab45aa5a426ed8ce5c3f11c957ef5ccecca8080808022448fdaaa7e6631e438625ca25c857a3727ea28e5658bb6a87761d9668637faacae15f907dd813ea1df4f85062fa5535765c198bb9d55293684a75d3a12e65215a8b410f2072244a7876ea32e7a748c697d01345145485561305b24a4f05ea3dd58373394ba3a7ca3cabec78b69e044b2b09e82171d82e6e3998a9ed1f82226cd4540bcc8c3bafa8c9c72512244d9a13701eafb76870cb220843b8c6476824bfa15ab63700b5d3f58338176990c8488a7c319480310b5ec39d23453839ff26116b29a91e20f834835c5e6f670961d7df8ff2a448fdaaa7e6631e438625ca25c857a3727ea28e5658bb6a87761d9668637faacae15f907dd813ea1df4f85062fa5535765c198bb9d55293684a75d3a12e65215a8b410f2072a44a7876ea32e7a748c697d01345145485561305b24a4f05ea3dd58373394ba3a7ca3cabec78b69e044b2b09e82171d82e6e3998a9ed1f82226cd4540bcc8c3bafa8c9c72512a44d9a13701eafb76870cb220843b8c6476824bfa15ab63700b5d3f58338176990c8488a7c319480310b5ec39d23453839ff26116b29a91e20f834835c5e6f670961d7df8ff1a8f1a0a90060a8d06f9030aa0312846a6b051a39d1ac8afa16dd707c278c2590b5b5399dd5dbaa2c87e9c6d04a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a049b529cd1d9b70dc216289fe9519c319964f0f7bd9458056da2defcf42743335a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028204a58402625a00808465122d36b90111d98301020b846765746889676f312e31392e3133856c696e75780000e904d98cf8ae07b860a0be31d422b4b017cc814dedd756cafcaff3c871779a6321284cebe91e5e1c2c0cb49b65be2a9bb41eabfc5480c8c75f0906339f62235d0b4352b3af1e38c79986cc1eb16880f26dd9c8f40bd8020890985d59f01bba4dd46df62be6a0c05414f8488204a3a0263c6cea09d25bb460401680cc3142f116c5a377f8ef11060e80f0f612f1c3168204a4a0312846a6b051a39d1ac8afa16dd707c278c2590b5b5399dd5dbaa2c87e9c6d0480f7464a0e50746e1283e82b6ea17ec53c71c61ed86665a300756b53d37dd3991346774d2ac3c242d8f0371f0ebe08f5af80757c6cd3e239212106d05d067064a300a000000000000000000000000000000000000000000000000000000000000000008800000000000000000a90060a8d06f9030aa04f09e6f36be8d56f196ab819ceab4de899dd91ea84d1a579c59cfe8d41f74269a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a049b529cd1d9b70dc216289fe9519c319964f0f7bd9458056da2defcf42743335a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028204a68402625a00808465122d39b90111d98301020b846765746889676f312e31392e3133856c696e75780000e904d98cf8ae07b8608ae8e9f3eeb44fc2ace50cb82e7922ccfad7571f507e89282474c970cd87f2f90cb7e3e22ef872e48cc904015c4792290b172b0e9aef2090a9ee653c0f258c215314c810b42b1a4399378cfeb7e8130082d7048bbc25c56373e4167b25feb51ff8488204a4a0312846a6b051a39d1ac8afa16dd707c278c2590b5b5399dd5dbaa2c87e9c6d048204a5a04f09e6f36be8d56f196ab819ceab4de899dd91ea84d1a579c59cfe8d41f742698048e891fd5b3f1eed759866fe722882c746dab531d47e972732640e42f49365b1348eb77bdc7425486f16a59b5080dd87b9406f1d532c37b8589e4b666cfd855b00a000000000000000000000000000000000000000000000000000000000000000008800000000000000000a90060a8d06f9030aa0ccdadba9c31c3462045f7552ec31591fc033d53cc02f66efe74a7a11527dd886a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a049b529cd1d9b70dc216289fe9519c319964f0f7bd9458056da2defcf42743335a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028204a78402625a00808465122d3cb90111d98301020b846765746889676f312e31392e3133856c696e75780000e904d98cf8ae07b860b5564a5fdce667a739c336d6b07beec17f8afcbc72da74f98e690327c32893b81ff51a6badcb7dfc0af7de042dc3b90e0467fef125d666956f3179b5330fc7a47624858eee5cb9edc93b45677417b742d213d97205770fcd0a36d6c409f551aff8488204a5a04f09e6f36be8d56f196ab819ceab4de899dd91ea84d1a579c59cfe8d41f742698204a6a0ccdadba9c31c3462045f7552ec31591fc033d53cc02f66efe74a7a11527dd88680299e2c8ee9446f79b09078581adec0382f5f0a5f49986493802bc10349e535d71b7e2d734818374617361443398ac0a3e3a343b7ca920586db67a7dcae60018101a00000000000000000000000000000000000000000000000000000000000000000880000000000000000120310a0091aaa04f90227f901d1a06ed7d26d8a14a9cd8aeb3f01960cae49b7e95dbd549fff6556694ea3ee3dc173a010790f90204b51f76a67de8b4bd23f62ea75f921641ff583a3ec5e8d681df975a06c664a574aeaa739d85b114d13a20a15330b02565910dfb142b6715b5742a562a051b92742fd280c4a2285b18197d40134dfe7d903b7d707cea1bd5f442a78a63580a019977eb86a7f4c991220db91b3be76de8c43b5f5ea5414ad2ae17d27226ff633a022a617263a20b5549555a9424a99ea156c9337b4b2009f9274febe93638918aaa0c993119ba273a56742e6fa6f92bb58a0120a3b3d27200340be21bc37ae8fdce2a04f3e6cb5f42f4cfe12e8e586e820edf8460ca87b27b4823c129d986c127e4898a07def82f69a90079ffaeaa69f6fda2b28363547c376948939c06aa8206c51c022a0b84308f4cb54366a086a4fdd936c40ab7ba0429ca9b7a624a6db6c5ac35c0b9ca041feda5565ebddc0a30be2e0fef75fe61729344ec36395f2f1e60865cd434a58a01223a2c45e23b4266f6b786bb346c31ea0c18ac94135d2f5138cc2851f7bf44a80a00d690f6252aa5118f41dce0eb3fdd420419d6d73ef7d51559385cab56a0308e2a09ab965be5ca3cbb09432f80709f918076cbad663afd466131fd184c8bda104c480f8518080808080808080a00f079d6471365442c66c0559bffebac0b429bc330e636338e9c5dac3bd3fbaf7808080a0e2ec5bfa0874d74ec0fdffc07602dab45aa5a426ed8ce5c3f11c957ef5ccecca8080808022448fdaaa7e6631e438625ca25c857a3727ea28e5658bb6a87761d9668637faacae15f907dd813ea1df4f85062fa5535765c198bb9d55293684a75d3a12e65215a8b410f2072244a7876ea32e7a748c697d01345145485561305b24a4f05ea3dd58373394ba3a7ca3cabec78b69e044b2b09e82171d82e6e3998a9ed1f82226cd4540bcc8c3bafa8c9c72512244d9a13701eafb76870cb220843b8c6476824bfa15ab63700b5d3f58338176990c8488a7c319480310b5ec39d23453839ff26116b29a91e20f834835c5e6f670961d7df8ff2a448fdaaa7e6631e438625ca25c857a3727ea28e5658bb6a87761d9668637faacae15f907dd813ea1df4f85062fa5535765c198bb9d55293684a75d3a12e65215a8b410f2072a44a7876ea32e7a748c697d01345145485561305b24a4f05ea3dd58373394ba3a7ca3cabec78b69e044b2b09e82171d82e6e3998a9ed1f82226cd4540bcc8c3bafa8c9c72512a44d9a13701eafb76870cb220843b8c6476824bfa15ab63700b5d3f58338176990c8488a7c319480310b5ec39d23453839ff26116b29a91e20f834835c5e6f670961d7df8ff").to_vec(); + let any = hex!("0a282f6962632e6c69676874636c69656e74732e7061726c69612e76312e4d69736265686176696f757212ad3b0a0b78782d7061726c69612d3112c11c0ad5060ad206f9034fa0df813ab13cd8fa64526bab2d574bd83199f358cf875b5a7ca34c55cc59fb7841a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a0347db7085bed92889205f4566fdeb71b36981b2662282e5b49f74f146e1b2920a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000282022d8402625a00808466a21174b90111d98301040c846765746889676f312e32312e3132856c696e7578000060b2e37bf8ae03b860b42b097ae5430552430062d80b2015710882c0520cf58dc6b987d0aa042840525bab13a5098af712b844bccf36b2ccb009fa3796f7088dec9a5dfcc0db6e4ab502fcca21d59598bd4f7504415662ec094b6ba1555c7faa0389468e45e11e8655f84882022ba0fe631870634a3823f363cdb9c6bd572b1a3ecaa9daeb98a784610a1cd1107e4882022ca0df813ab13cd8fa64526bab2d574bd83199f358cf875b5a7ca34c55cc59fb78418008487b8053f33e79d8758655252a23e25ce9f3440557d0ed67c80700633730674c5c682fa86414f136befd54de6023cbbb74bc48edc438ad136bc34f520b264100a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa09e0419600f424df6786dbbdef3f774c0a3d9a9785c8e3aec85ec4d95a2a526ada01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a0347db7085bed92889205f4566fdeb71b36981b2662282e5b49f74f146e1b2920a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000282022e8402625a00808466a21177b90111d98301040c846765746889676f312e32312e3132856c696e7578000060b2e37bf8ae03b86099480987f69ba68b91ea25863b7cc7881fa57156c57f04b9a1ce33fa6766522d1ddafbb4b0ebd913bedee575cf18790f163d68c5d8fc5d389206ec1baf04b7daf1b17c9b5e688f29e71bfc5c40c5327dd6a36a7fd6e043305f6fe01da6fc77bff84882022ca0df813ab13cd8fa64526bab2d574bd83199f358cf875b5a7ca34c55cc59fb784182022da09e0419600f424df6786dbbdef3f774c0a3d9a9785c8e3aec85ec4d95a2a526ad80aab31b654039b4edef9af34f1bfbff4999aafd9c007bb3925378e865a8fde7d9693646834fc0323d375029594e363a4d96d49d0d5bc1dd6d98ed87d13fcfc4a700a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0d71391dfe369c3f939c86aa6c3a25649a5ce9c298549e075981d65dc3278fadda01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a0347db7085bed92889205f4566fdeb71b36981b2662282e5b49f74f146e1b2920a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000282022f8402625a00808466a2117ab90111d98301040c846765746889676f312e32312e3132856c696e7578000060b2e37bf8ae03b860acd5509943efb944b23870db31f09b536731993d75078450bedefa5df77ea416d2d54be798d452d4562b57571fcf3ec00596cb4516d86b82a52081275c9ff9a35aed899b63791acbff7000f3c907c9d9f61e386c8c0de5ea79d67fd49c5675abf84882022da09e0419600f424df6786dbbdef3f774c0a3d9a9785c8e3aec85ec4d95a2a526ad82022ea0d71391dfe369c3f939c86aa6c3a25649a5ce9c298549e075981d65dc3278fadd8076a78528fffc86138b8155eaf036c0ccced82091d1cd7be5e7445d9d44b512907766334023ba1ac6b5376b39619e7198467598e549b284dcd065b4088ee0be0600a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310ac041a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0cb21354718f7d012561dacf2274405cdd9bccd532afe18206bd26bf60e96c853a0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a09e8d71308bd38616ac52a39498cee9fcf29c440d9aacfedfc7143772c77ce54480a0a74e307420bf9966d5db9a83ce48edc32c7a8e43328c6373de6875cefa04ad7aa004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0d4182165b298d7b52b0f2064d19ab8bdad2b3955fa5b3d85c00673beb97e124480f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a03f47312ca98ac1f6ae9db9752c2a33529723b64e654d87f7847cee0382edfb55a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e56592b50b17b5348f1aebe4c50d87c59b55223abe57c9c3df76cb4a96211bb393aacd440bac5f71ea3fc481abff6270142d2244a7876ea32e7a748c697d01345145485561305b24aed19f6cbeb659e104b4657c2e41822087506cb58b037aba5599314c2c4bea0ef4d3cbbc449b24abf396cfd71ac07af42a448fdaaa7e6631e438625ca25c857a3727ea28e56592b50b17b5348f1aebe4c50d87c59b55223abe57c9c3df76cb4a96211bb393aacd440bac5f71ea3fc481abff6270142d2a44d9a13701eafb76870cb220843b8c6476824bfa1595bd9f541fdb277d2bdd5ff223f95eb83f8d2b465c1bac3cf2d0bc551ad01a9037a4af083d66eff89b34200745db92cc300538061ad91e0ad5060ad206f9034fa0aeef6b8a15e0109c9838875b033b5c54d21c356cb5ddf395eb109b9b29ae694fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a03e5bfca057d64cd5c54c82f5e213f8e7993411a5a490c0b93358f6def507e8d4a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000282022d8402625a00808466a2116eb90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb86082b910df7cee75733375fb7716c34b14c1ce27f283c2d87ea0e2b2a0de42d18bdd724766b3a73d5daaa25befaa814df815605e8881819d421c8703100b7a93d1a22c89693625b4370d4d87b85ed676661ce65d46ef0c5c8325696892abf0d5d5f84882022ba03986751eb813b176c13e29485332e635df862b515516501e87113f50b655d80c82022ca0aeef6b8a15e0109c9838875b033b5c54d21c356cb5ddf395eb109b9b29ae694f80af43c5cc71b487cbe16b6771635dc751cbd6231274a3bbf87ae8b38c3319e5f54eb4e0a8186070727a19eb749b2e70068b7c505b1ed8b0dd7d6a595e2bf5db3601a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa04a9481f17c19c739ab1961ffdba488b234d37254da0ec7e95d8cf5d4ad54893ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a03e5bfca057d64cd5c54c82f5e213f8e7993411a5a490c0b93358f6def507e8d4a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000282022e8402625a00808466a21171b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860a41a9347a1766d7b59a6f4eb4434f89a5ff5e52df18b90baf4588374a65b578fdf85c4c605b325468883f22a49ce28bf1194955ae44b6de878a8def6b4c36cd5bb669be37d4a31bb7b48e45c7e0fe0d8fd43e86ba60871b6e1b7c731498d0df4f84882022ca0aeef6b8a15e0109c9838875b033b5c54d21c356cb5ddf395eb109b9b29ae694f82022da04a9481f17c19c739ab1961ffdba488b234d37254da0ec7e95d8cf5d4ad54893b80292058b3eeab2626c29d676db526a6a0d8b739a59f9d7971e5fd3e96192321e4759aa81a6bfdd5a211e3dca1d29f20fc5feffdb3261fb2afdd2fd9b4f9607fb201a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa04a6b366f150065827cf5954904fdca9da5073531b4aa5462e86636feb61890aca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a03e5bfca057d64cd5c54c82f5e213f8e7993411a5a490c0b93358f6def507e8d4a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000282022f8402625a00808466a21174b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860a440c540974a6217ff340cbe742520fce50a18f18553f4816fdb43d9a74092ebb237ce4cce2a10f0e6d7b6ec58cf53990b91b8d2279eec1391748eab3a605cf1d900fa267dfc21cc8ebf35cb138c10287d49b3a4c1c5d18bd7727f74fa64e46ef84882022da04a9481f17c19c739ab1961ffdba488b234d37254da0ec7e95d8cf5d4ad54893b82022ea04a6b366f150065827cf5954904fdca9da5073531b4aa5462e86636feb61890ac806014de9b2c697f9b78ac9c86cdcc45bd19b3388569814a24bcbbe570a47561fd713af78490598f2d211f13cf1a5ed4bf299c1c1df8c677bd018b695c9f8339bf01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310ab041a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0d1c5c078d5c2983649e8200a84d8fef4d4c1ca8a06ed8f7be21f82c23a910edaa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a0f9858d51200cb595d4f158c848af32e29fa61db4ddea7cde4006a7cbc306ef5880a03dc9ef066e7332efc09e4f620aab588d5465c1ed3b813c912928f1ffa44503a6a0a4aa3b0d5510f907876be1bff95c5867b088e8464e4ae75e45d016c5ac21c0faa00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa076094ead9021f5472bb12b03aeb521e09d71029dfa5dac90afa7cb44cbdfc5bd80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a0579a97aa89dbeb98396792baa31c4a7ea8e2f41da084140f07bb4bd655b72dd5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2244a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62244b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be32244e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc12a448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2a44b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be32a44d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32a44e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc130083808").to_vec(); let any: Any = any.try_into().unwrap(); let misbehavior = Misbehaviour::try_from(any.clone()).unwrap(); let mut mock_consensus_state = BTreeMap::new(); - let trusted_cs = ConsensusState { - current_validators_hash: misbehavior - .header_1 - .current_epoch_validators_hash() - .unwrap(), - previous_validators_hash: misbehavior.header_1.previous_epoch_validators_hash(), - ..Default::default() - }; - mock_consensus_state.insert(misbehavior.header_1.trusted_height(), trusted_cs); + mock_consensus_state.insert( + misbehavior.header_1.trusted_height(), + ConsensusState { + current_validators_hash: misbehavior.header_1.current_epoch_validators_hash(), + previous_validators_hash: misbehavior.header_1.previous_epoch_validators_hash(), + ..Default::default() + }, + ); + mock_consensus_state.insert( + misbehavior.header_2.trusted_height(), + ConsensusState { + current_validators_hash: misbehavior.header_2.current_epoch_validators_hash(), + previous_validators_hash: misbehavior.header_2.previous_epoch_validators_hash(), + ..Default::default() + }, + ); let ctx = MockClientReader { client_state: Some(ClientState::default()), consensus_state: mock_consensus_state, @@ -996,18 +1023,9 @@ mod test { other => unreachable!("err={:?}", other), }; - // assert testdata validity + // assert fixture validity assert_eq!(misbehavior.client_id, client_id); - assert_eq!(misbehavior.header_1.height(), new_height(0, 1189)); - assert_eq!( - misbehavior.header_1.block_hash(), - &hex!("9432b9b136e91a12cea5e9cc363bc821e90da6c7b2d7f369533afa746ac21508") - ); assert_eq!(misbehavior.header_2.height(), misbehavior.header_1.height()); - assert_eq!( - misbehavior.header_2.trusted_height(), - misbehavior.header_1.trusted_height() - ); assert_ne!( misbehavior.header_2.block_hash(), misbehavior.header_1.block_hash() @@ -1025,42 +1043,38 @@ mod test { let client_id = ClientId::new(client.client_type().as_str(), 1).unwrap(); // fail: exactly same block - let mut any= hex!("0a282f6962632e6c69676874636c69656e74732e7061726c69612e76312e4d69736265686176696f757212898e010a0b78782d7061726c69612d3112fb460a9d060a9a06f90317a0a253fa96c80a63c58a92c2169edc61d58f53912fbecf0a3d23d95ddd7d375b1aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479469c77a677c40c7fbea129d4b171a39b7a8ddabfaa0367319f8df31ff4b616b09c5d0877147904002cbeb93701e2bc2291d3f85e373a0a36d378b3813df6d2cfb735f98b9f1c2ad274767d70d2b83f01df65bd7060c7da0c07110486e8eb7be3528220485458e1904554e77a709835bcdf102de08b61445b901004222e610319851925ec8a154c538000d1618a08003578c18285805003b321c97a7345044c970940be2052cba00125380a2085c53144f23627c415c3349272ee714926a41234418b9af7c04bda5080931a51709a3547d9f82a30db42080012c05016881359b46c3820001bc98e1428bdb2c590c6f88418c3d70c47a1048c8a48934bdb1342c0b5c54808ca48044270ceb88a536f54270754b07051c489bc4f02586c0841997d889a8243816842b8b2498200a90d518a8c78213412a2c515b446c2584150775092b9286a6202b8846f2812415a35019ee011433114cfea021f67e431a0305206470020364a623a020894870960ea0c2764e4b95ca4e10238b10a9028401eaba0b8408583b0083ad346e846516831eb90118d98301020b846765746889676f312e31392e3132856c696e75780000b19df4a2f8b5831defffb86081828df4756db11e725568e085da9ea4f1db63f97645e76c91f77d22ffef7200e0a8f06d9f2f2698f62d99c972c488ba009b507f36b346254e782534110e04a20772e2dd6a2ba12f482b478cfada1981fb46fe33d31a08ebef4abaa4ac2b83fcf84c8401eaba09a03009339cf4323f2c5efd3ec22eeb696e0b0a4e6ab60ed9f9d4c8f23bf227ac7a8401eaba0aa0a253fa96c80a63c58a92c2169edc61d58f53912fbecf0a3d23d95ddd7d375b1a8083ad988504ae27211e4a676510c51568f555d6b95545410b209b6761282cd3e679e277a8969b5f5d97101ae220174d69e960ce9f13bf7fdf0661c368b1df347400a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a0ec996d8163dd118f6fa5e2a83a7d19fe665a2317facaa7ae9fbc95e6aca7e7cca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479472b61c6014342d914470ec7ac2975be345796c2ba0d4d38d061e7a8eaa7beaf72bfda8e61ab5bf52aea4315b273e29a7bdccef7cb8a0087324763ee1c00c9ad8d09121f2d2f56d80d593342bcd998e4fca26f0e03153a05eea513d92cac961941b786a8827e4d1375885b0cbb90af62fca8e0fd9285ed3b901008d6b62622b1c923e0b335b6584226a3b955878d0deba0ec87a78e16a316a2034876953d9d2a6e610c7b1faa45f9e6f6381e1c118207bbaa650282513dd3c2edc0cd7c42ebf6acc6e21ad284b7724473d2675b0224fd6e2bcb1b64eb490b0cf294f3fb9755b072fad587b8b7881341f08fc157c55c23a543e2f65949e4fbba4c5f5daa92c0eaf839b9d8ae4888d026c1eb46cd4edb96a619a1a1584f8f4ac0f2402d2b9857249930c8528f166ee9e4e59c18210453d06b1874d31a82a05f678abe04a1e9a98811d5fd6a848ed024c78b0a6fba25c9a42e6361513510e79aaeea810d1d805d4e0db90c90b2a92530081e349946b6893bc8079f17746207c3d1158028401eaba0c84084fe2c683efb91f8465168321b90118d88301020b846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5831defffb86083265457e59114983f1076e6afe3914e8f6c68afcb50c434f49e3d4f3e380208adde4d348c10d83a4caa577dc8f875050aace673b180818bc9c53c44be471a089d2773a9088356409b7668f24e0221f5dc0e12d121552cf2554a54710fde149df84c8401eaba0aa0a253fa96c80a63c58a92c2169edc61d58f53912fbecf0a3d23d95ddd7d375b1a8401eaba0ba0ec996d8163dd118f6fa5e2a83a7d19fe665a2317facaa7ae9fbc95e6aca7e7cc80fea86520fb3bdd71a0744ae6311c632107f640536f647f352c4d76cdefc0fe3f334095862d3f08362d50104caa4dcae5f15cb24a25a6e7c413ad04b20e7d6d1901a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a0937afa96827a173a5ab83721cc146cb8f10dc87ba31ceff7e2395d2589a904dba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e2d3a739effcd3a99387d015e260eefac72ebea1a0711c94607e53ea254337a19dfe928741d406c0217becb0b51034fc91a4b2e88ea0e540e2e257a6edbb482543f15e1690410b70cddc7b8111f48de4c688a35caca1a0ded39245b638233ed2ac16389abb608f6329d48557888cd16de33d6b510873f6b901000e220e06afc4d15833201a459150012f1a51400005088c06383961403a2c0c00a42c3111001898020123ecf3081a00838e000418000b60a00490a002003f2a014458d8408570580b0148802b24a00428a132222861f47b86248404b4c02316210b2c802b0aa209d500c98d000145090d38c84409084cc420b944593410ca38a2c83c80a40b38108af0d84420240404fa2a740e812ca604ba38819241410b9070060182011f801211019aa03c0b8004a31c8b47204a0e450812f803a206402260a40b971220084c065500489b50315423a0402510d52900144513444e1421ed5d1511a45d1822275801b522040090017126448c05132a04e85608991043990849018401eaba0d84085832a78389fc6a8465168324b90118d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a2f8b5831defffb860accd42f5a790b23a42c750634bd4c632b68b4a13d9e67a23fc88e634c1f5be8b8824355e90f5e6bcb23af9f0ecdb041c011c645770184427d940f1078c0f20aa6f70aa3e68944f9e588ec0726febd32ab6519295e3eefdfd66ca3ff0a57e6e3af84c8401eaba0ba0ec996d8163dd118f6fa5e2a83a7d19fe665a2317facaa7ae9fbc95e6aca7e7cc8401eaba0ca0937afa96827a173a5ab83721cc146cb8f10dc87ba31ceff7e2395d2589a904db80c68c3a1187742f4228a35df126397c068f0d529182962a834f230031471c12bc6d4cc917d21556160579a782e799fdbce7d5bae9c67027ac6f9860f540f768db00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000801205108af4aa0f1a951df90e92f90211a02bff590463eb4f2fb98586805a6591c49ad02eb38211ce40238beef315d2b1a3a03f20d9b30890c082262b4ebcb9c089af0b95a18873fd3c0b1a13e0d0c71137eba0c0649e9f0a6040129bcd329483228eba044da097d400621ab85b5351d2980b40a0304852b72a4c75c7d71e3946ef983cf4c1f3c2b478c8997870a1d4454ae04dbfa0432d943bbfe2b6d9f62df84439769f8ea76f9213c6fcfdcf2052d5c31dcdf16fa00c4d39f0619caa3ae86e99de2395b94ba29a52ab6e4966a5bb4b138ae39e0c70a0384ee242954ec95a8f3372527b557488894506ab1a9fe80fc8381ff15216e103a022bb93d7f4851836b855b2570e2e01270585595c9792cc4e93a437a4e474bb5fa0d02fec5b104fcc8919ab37aff38a323fb06bb05663078b901c7dd54306d3caeda0f18f265a00fedc81f65cde8e79d8909c9eaf01cb1badafac441193c3911a50cfa0a475a4d413336a0497c6c412db1f4a0b75339d8ebaa318ead92b01926f904668a08b350addc0ac0af1c475f6ea8c89f9e7bfd2f08db1496d88a4b9b8d7e68b775ca0a93aa453df1f6fea8e6586b761752c988bebc9d8919fce66a2dc07b13b516317a0e88647c53c3837076340c8af5dd6e7d6eae1e979748907cc77735a2fa61fe3b5a03558b2e214bbd1e4f1066b9444fd27491b8cd594727b4df2c6c40a66ee092e48a04b8dd919d1cd6c0dc1c868e8b17383212a9291ee4c6129b74927822c836d96f580f90211a082dfa0895f58c8ab219b1a3495c930a91ced1024bb93d17db00e25b951a6c619a07daeef642e3fafcd93260f2c8486ee75803c32795ea83152752c7f298ba98481a0416d5ba0562c59a16a92991b267cdb40b25734856902f5599db0ebf64ce4ea40a006a001e9a09963a91a4e2fdea6a238d4b540699e8828085b460dab39744547c7a01dc72e0048890365d8fbfb7c5b1c8ef52d49e41e089d99f52fadffe3efde1303a0942505b8e8a3ec1f16bee602466ef6605139cce2b5802355aecd2de1def8363ba0096a2585a6d4d2912c5387d5998f22455a1baf48894c5f89621d22721202f238a0c798b5904ca51608776665eb627ba3a32ecb75eaf20cea825ece8f9b8a7a44f3a076f5e9f1ff4e8b68028f8dbf07711a9e5235887749da2db07d8c7ca23d1c06dba0019d4d8661b0e52876e58c1cb072c5c2aef8db86d35288be6ddbf6cd782eb5f6a01c418f5263baafdae54580467f5e50ec141611331f53db37d838c1671bc6a25ba0a0fb254b54da6444d91d0b6585c4a2fcdf9e19b10357377fd5699b4bad8adab6a00b841477da486c5819fd12285e8f097c92b317c9e239954f5cbba1c70f679b4ba0612b371378ad1d8cc5e0954a111df8e0c8ea0da63300ca1126fb1a54338b32f4a072a4f633843d50afdb0d3a76464892f1c392579ec74f6df6cf1df231ba4ab42ea07734e834476c826ab88df35eb30599174a9f863d17d18ce04f87f34526cb6fc480f90211a02fedb0b9b16e327962ff519dfc137fb4e25408054dc09c6cf8d97fcc8c58f1fca03869abaa6f82c34c1aba13cfe0b7ad104312b8ca918060c181dd406c8a99260ca0f753573922dd3666bd8c5dbd5b4ce6de8a8f0800188c034d383d8916a53ce3efa005613369534c7d926a4b06e352e6d17532bc802c0fcedd13073e68c41b99901da0c5daa0a98986bab70d997d7faa4b55ddbcb75bcf7cd71d7950d145222cb3e21fa02718fac0f09350134ea331146441ad6005f8a8c20b9673f5b4bb1d9cac9f2163a0895fe437ecebfb9a688f7de6f3e9ef5118168fc60d9eee552eb504d64d301f6fa0b4cf1ad7a7b3f08bc8842186fcd78ff7d746763fcae212432d0f20a50be4fb65a07396b72a68947b922b056495abe200f446a5fa9b01fd098d17a76a2672b9515ca09a877e342351f9e10dea0fbf7478ee67c215bfd821da88208b9fcf63bea39bfba0b5ead9f9ba5a3ac8c888cb19af13e8a3d279474818054d335b28e81c431cc72ea04e66c0882953c62e542817724480b4f8d7a7944b3dee7455b249be68b5b9990da03a1aca9f115f2d3d71ee1cc202c2129d6f72c4f80b7b85128d54f9be9cda8c2fa01c1a35b8aa431b2a845c34b464542a83220b17e4dd1a4d4774b1807f1f9c9e23a03b2492dac5c5619f8c84fc0969ff24f5695bb4363c22c4120c86d2bc128aabfaa0c30d11204878acb9ce6a7931150e9ec10f1a659076ec3c1528c663f1897f85e180f90211a043beb9ae278028ab0e6ae1dd97bfc1adc7da5d5b35418cde1372ed15dc60d844a0969897f77040974812fdc243499998d5a2f808b010e3e743fff5bb1cf06701b7a072a62f95c81d3849bc02102bcb66b5be775ad3b68cae7967451e6a13c48b6c43a0488199752a3a18aaaaa52b07d5a306826c4ccb2afe3cb30058de3e361dee74cfa0a63fb5ff17b1ca7f9c095cd9a888f4fd493a3379cdc2a0cfb49353c854923fc7a0ce7a2593ac4b8c89ad4c5fde8940d9695e969cfe6eb6a614954a48bcfd715843a0cb8b4d0264778a2ab04b96777ffe78a5ee62483a87446fceccb37813cda25b60a008fac15554b1c384ad91aa696e7e5e5454dc0c0fa343bb26b48a4f34ec95f785a0f1811154dd01ffd9f43443acd407e0beee53bbd03f40f63b7d993681182f0289a0a620126c5db0919a29b4b27c728dc42d2d63015849527be64acd0062b575c0eea088d3cde1a49a0ac95f076d1e15b3fde9cefd0f7e308f53b3aa466eb0385aec50a07f99a989d621bd1b59fa51d109f6413c9cb7f8ccd704dbf13cfb27bebec8f1b1a04321111d914057fe87d18e8c6f4128c6c7778fa2b73d435f0b2562c5910361a2a07ee88a697a560dc7023a840f16df54c599dc345e787927bf6628963e782a6847a078d58eb776d8d9dd6dbdbdd830b0350bd0427b15678ef457da5d41ec2cca708ca050e0c4585785b9c800e24c4c4e00599d7e5c4e6d8f3363979ab6c49ed514f12680f90211a011ff0a2d404fd7ed97509ebaa806f2a5ba09c5cde5ff596903c4313783487509a014931c578b05f5948939281aa31d2bc8b05b01c6932c45bf7a70972a430575c2a07272592f567daa667135799961e9eef529a6cd754395e39694d9452ae24a8797a092b17ad714173ec4787f0b3b9d2dfa96680861e093b5121441ffcde64183d074a06db41a6efb6f94c7d185f76deb8bb00468715bf6828fb63db31b880a6050c54da07ce695737ab0d4bf9003a06ce83b11e75d81fbeb47c013b41f9c2e00a97cb87aa0dfe63771f833e98a5aeff54d9dd5a8dcfd89ca43c23644b18ec8e29ab8ccc287a0a327c817dc8a8ea3a5d3ca3cb55169777a1bfa30fe9f0df842eb3978dbd6737ba053683114bdaed7819b30ab8baec1fb9a2a96fee4dabc72f319cec9869da3b0b0a04d98297a896312d18da40240ed9a527f4c01c73edd3ea1f7c28338d1d863d97ca070451b5f2a402b497659eb18e648ac46f39c0068cc91436eb0b082b1d06dd63da066e866f800200512b0d3e534c547f4d2012429152cc9693bf1553cc22361627ba003fc4e648aafdadd7a9fa7cb534103f08dc699413ecda22bda46898bfb792429a0b46a167c66b50c74227d03a68971e124fdd011d6c90f5a08f6fe30ae34de603ca0a7ced66271235bc27b154f37bee6d9a1366cd253176c96de707d124fcc593c35a0f4f09b104a86cefc5c282d393b415e6c224eb8a463386448ebebfad9f9f53c9680f90211a05f93540f4317a4c6d8b73556a7ffdab6fcf0aa36af84b8c4bd2a3e7114e2da4ea05dd8c13b1b83485911f5e1185669f7d5559c260193a72e52597a3e80736c248ca03d50a67e8ec93696c35865d9f03814e95406c8d04e5decc320b9a24e5beee1baa0a928e2ea8773ba69dde5344d69069b237667dbaaa69e86133d4e444e432799b1a0ebb2cbf0c3314ddf681f21a29fa17b320094684ba35e725bc36bbc407821cfa3a0762aeb8161d2b1b8a5ee51d1ede36f51cc2dad7e0c4d0ff097b89c831aff8c35a0957a8eaaac924688482d21a95b7a7f01889ab39a7a50d58efaaffa9e486ae071a046c10b0c15aa83973ea4b108f50bad2638941550fce7c9308c8b968abee271f8a08a831384faa68f9caa047a6200464e11cfe5f9f700a5ed9435e5241d9d2a501ca020630d0f41d1f38c61fc8d3fc6170f6f11fc52ade454930a3b5e4f4491b47467a04539a99793f29484fdbd39b606f27265499acb3c24461f48858655f07166f0dfa05fd40548cfae17d12e103db98572f22cdc8dd3ec670be570727a7ff68f6bce9fa032efe866f058f79ef06de75f682e10773576eb9fca3f950fda96ea9926784685a05c170d685d29417781f678b746174c7500e7c228b4bd71bcfe9f5421742a0b67a0c3fb71b77522f06c4a4e4cb7029e7faeb747b8e446460586ea0d5e9abae68cd9a03f2294bf8bea287c7afafde4b39aaa56716230ef425ece688f6a78fcadf5f49e80f9013180a0c2cb770a3d18eb1214a782cc81b79a7fd772716c2d050ef66011095c3774e8f7a08fc7d7da06fba7ffa69b095aae41147e3a55b89644682057cedab705ba7aefd5a05975b434f69398107a4d1729f8f56e75247df09c65b1a750797818607bf118df80a026cea4c13260b2a1dd74bb6fcc7cc36162d2856ce691a36165c633ba68f7b783a0f7b0c667509a4ce937c487b45bc53c0700543daf4f8c127fbe475b4e1084d2328080a0454eca3fcc32afd4c4000ccbb47732bbce342b1a9d374fb5872162f2c873625fa0b3e6c44579a731cc730a5472e83c6098fa2943e5b2c72f4475f0afea76848a87a03b8c951788b8c93366aedbf88f6c1ca6085cd0249025ce542f19294b40bb92f180a0a10cfa51ae290afebd64a5b530db7088fa0b02f22ce9b0838135b422b885dee5808080e482000ea07b2632b8b97e159d88f112a8dd9d44df2f3c4502e0c79a29297ea7f61f41f311f851a030590b16841225b9590cdc95b19176201d442ca0b931c6e4314d20a1c772ea9ba052e8f9f247cd159c65b304863d444087f6a60d7dbec3a0e4fa09f007b5a1c64f808080808080808080808080808080f86c9c20120c458c4c09a9448628f84e81161b308d5c4041a3d3a1ea329d0eb84df84b0487400e8b4f1c9c00a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47022440bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e22442465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c8162244295e26495cef6f69dfa69911d9d8e4f3bbadb89b977cf58294f7239d515e15b24cfeb82494056cf691eaf729b165f32c9757c429dba5051155903067e56ebe3698678e9122442d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab022443f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a224461dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d25224469c77a677c40c7fbea129d4b171a39b7a8ddabfab2317f59d86abfaf690850223d90e9e7593d91a29331dfc2f84d5adecc75fc39ecab4632c1b4400a3dd1e1298835bcca224472b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a5122447ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e22448b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d788694852244a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b7412244b218c5d6af1f979ac42bc68d98a5a0d796c6ab01b659ad0fbd9f515893fdd740b29ba0772dbde9b4635921dd91bd2963a0fc855e31f6338f45b211c4e9dedb7f2eb09de72244b4dd66d7c2c7e57f628210187192fb89d4b99dd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002244be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cd2244cc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a4192244d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce7392244e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d212244e9ae3261a475a27bb1028f140bc2a7c843318afd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002244ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c1921832244ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5b2244ef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd0756e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd02a440bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e2a4412d810c13e42811e9907c02e02d1fad46cfa18bab679cbab0276ac30ff5f198e5e1dedf6b84959129f70fe7a07fcdf13444ba45b5dbaa7b1f650adf8b0acbecd04e2675b2a442465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c8162a442d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab02a443f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a2a4461dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d252a4470f657164e5b75689b64b7fd1fa275f334f28e1896a26afa1295da81418593bd12814463d9f6e45c36a0e47eb4cd3e5b6af29c41e2a3a5636430155a466e216585af3ba72a4472b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a512a447ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e2a448b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d788694852a44a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b7412a44b4dd66d7c2c7e57f628210187192fb89d4b99dd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a44be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cd2a44cc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a4192a44d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce7392a44d93dbfb27e027f5e9e6da52b9e1c413ce35adc11b313f9cba57c63a84edb4079140e6dbd7829e5023c9532fce57e9fe602400a2953f4bf7dab66cca16e97be95d4de70442a44e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d212a44e9ae3261a475a27bb1028f140bc2a7c843318afd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a44ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c1921832a44ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5b2a44ef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd075").to_vec(); - let any2= hex!("6e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd01afb460a9d060a9a06f90317a0a253fa96c80a63c58a92c2169edc61d58f53912fbecf0a3d23d95ddd7d375b1aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479469c77a677c40c7fbea129d4b171a39b7a8ddabfaa0367319f8df31ff4b616b09c5d0877147904002cbeb93701e2bc2291d3f85e373a0a36d378b3813df6d2cfb735f98b9f1c2ad274767d70d2b83f01df65bd7060c7da0c07110486e8eb7be3528220485458e1904554e77a709835bcdf102de08b61445b901004222e610319851925ec8a154c538000d1618a08003578c18285805003b321c97a7345044c970940be2052cba00125380a2085c53144f23627c415c3349272ee714926a41234418b9af7c04bda5080931a51709a3547d9f82a30db42080012c05016881359b46c3820001bc98e1428bdb2c590c6f88418c3d70c47a1048c8a48934bdb1342c0b5c54808ca48044270ceb88a536f54270754b07051c489bc4f02586c0841997d889a8243816842b8b2498200a90d518a8c78213412a2c515b446c2584150775092b9286a6202b8846f2812415a35019ee011433114cfea021f67e431a0305206470020364a623a020894870960ea0c2764e4b95ca4e10238b10a9028401eaba0b8408583b0083ad346e846516831eb90118d98301020b846765746889676f312e31392e3132856c696e75780000b19df4a2f8b5831defffb86081828df4756db11e725568e085da9ea4f1db63f97645e76c91f77d22ffef7200e0a8f06d9f2f2698f62d99c972c488ba009b507f36b346254e782534110e04a20772e2dd6a2ba12f482b478cfada1981fb46fe33d31a08ebef4abaa4ac2b83fcf84c8401eaba09a03009339cf4323f2c5efd3ec22eeb696e0b0a4e6ab60ed9f9d4c8f23bf227ac7a8401eaba0aa0a253fa96c80a63c58a92c2169edc61d58f53912fbecf0a3d23d95ddd7d375b1a8083ad988504ae27211e4a676510c51568f555d6b95545410b209b6761282cd3e679e277a8969b5f5d97101ae220174d69e960ce9f13bf7fdf0661c368b1df347400a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a0ec996d8163dd118f6fa5e2a83a7d19fe665a2317facaa7ae9fbc95e6aca7e7cca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479472b61c6014342d914470ec7ac2975be345796c2ba0d4d38d061e7a8eaa7beaf72bfda8e61ab5bf52aea4315b273e29a7bdccef7cb8a0087324763ee1c00c9ad8d09121f2d2f56d80d593342bcd998e4fca26f0e03153a05eea513d92cac961941b786a8827e4d1375885b0cbb90af62fca8e0fd9285ed3b901008d6b62622b1c923e0b335b6584226a3b955878d0deba0ec87a78e16a316a2034876953d9d2a6e610c7b1faa45f9e6f6381e1c118207bbaa650282513dd3c2edc0cd7c42ebf6acc6e21ad284b7724473d2675b0224fd6e2bcb1b64eb490b0cf294f3fb9755b072fad587b8b7881341f08fc157c55c23a543e2f65949e4fbba4c5f5daa92c0eaf839b9d8ae4888d026c1eb46cd4edb96a619a1a1584f8f4ac0f2402d2b9857249930c8528f166ee9e4e59c18210453d06b1874d31a82a05f678abe04a1e9a98811d5fd6a848ed024c78b0a6fba25c9a42e6361513510e79aaeea810d1d805d4e0db90c90b2a92530081e349946b6893bc8079f17746207c3d1158028401eaba0c84084fe2c683efb91f8465168321b90118d88301020b846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5831defffb86083265457e59114983f1076e6afe3914e8f6c68afcb50c434f49e3d4f3e380208adde4d348c10d83a4caa577dc8f875050aace673b180818bc9c53c44be471a089d2773a9088356409b7668f24e0221f5dc0e12d121552cf2554a54710fde149df84c8401eaba0aa0a253fa96c80a63c58a92c2169edc61d58f53912fbecf0a3d23d95ddd7d375b1a8401eaba0ba0ec996d8163dd118f6fa5e2a83a7d19fe665a2317facaa7ae9fbc95e6aca7e7cc80fea86520fb3bdd71a0744ae6311c632107f640536f647f352c4d76cdefc0fe3f334095862d3f08362d50104caa4dcae5f15cb24a25a6e7c413ad04b20e7d6d1901a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a0937afa96827a173a5ab83721cc146cb8f10dc87ba31ceff7e2395d2589a904dba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e2d3a739effcd3a99387d015e260eefac72ebea1a0711c94607e53ea254337a19dfe928741d406c0217becb0b51034fc91a4b2e88ea0e540e2e257a6edbb482543f15e1690410b70cddc7b8111f48de4c688a35caca1a0ded39245b638233ed2ac16389abb608f6329d48557888cd16de33d6b510873f6b901000e220e06afc4d15833201a459150012f1a51400005088c06383961403a2c0c00a42c3111001898020123ecf3081a00838e000418000b60a00490a002003f2a014458d8408570580b0148802b24a00428a132222861f47b86248404b4c02316210b2c802b0aa209d500c98d000145090d38c84409084cc420b944593410ca38a2c83c80a40b38108af0d84420240404fa2a740e812ca604ba38819241410b9070060182011f801211019aa03c0b8004a31c8b47204a0e450812f803a206402260a40b971220084c065500489b50315423a0402510d52900144513444e1421ed5d1511a45d1822275801b522040090017126448c05132a04e85608991043990849018401eaba0d84085832a78389fc6a8465168324b90118d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a2f8b5831defffb860accd42f5a790b23a42c750634bd4c632b68b4a13d9e67a23fc88e634c1f5be8b8824355e90f5e6bcb23af9f0ecdb041c011c645770184427d940f1078c0f20aa6f70aa3e68944f9e588ec0726febd32ab6519295e3eefdfd66ca3ff0a57e6e3af84c8401eaba0ba0ec996d8163dd118f6fa5e2a83a7d19fe665a2317facaa7ae9fbc95e6aca7e7cc8401eaba0ca0937afa96827a173a5ab83721cc146cb8f10dc87ba31ceff7e2395d2589a904db80c68c3a1187742f4228a35df126397c068f0d529182962a834f230031471c12bc6d4cc917d21556160579a782e799fdbce7d5bae9c67027ac6f9860f540f768db00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000801205108af4aa0f1a951df90e92f90211a02bff590463eb4f2fb98586805a6591c49ad02eb38211ce40238beef315d2b1a3a03f20d9b30890c082262b4ebcb9c089af0b95a18873fd3c0b1a13e0d0c71137eba0c0649e9f0a6040129bcd329483228eba044da097d400621ab85b5351d2980b40a0304852b72a4c75c7d71e3946ef983cf4c1f3c2b478c8997870a1d4454ae04dbfa0432d943bbfe2b6d9f62df84439769f8ea76f9213c6fcfdcf2052d5c31dcdf16fa00c4d39f0619caa3ae86e99de2395b94ba29a52ab6e4966a5bb4b138ae39e0c70a0384ee242954ec95a8f3372527b557488894506ab1a9fe80fc8381ff15216e103a022bb93d7f4851836b855b2570e2e01270585595c9792cc4e93a437a4e474bb5fa0d02fec5b104fcc8919ab37aff38a323fb06bb05663078b901c7dd54306d3caeda0f18f265a00fedc81f65cde8e79d8909c9eaf01cb1badafac441193c3911a50cfa0a475a4d413336a0497c6c412db1f4a0b75339d8ebaa318ead92b01926f904668a08b350addc0ac0af1c475f6ea8c89f9e7bfd2f08db1496d88a4b9b8d7e68b775ca0a93aa453df1f6fea8e6586b761752c988bebc9d8919fce66a2dc07b13b516317a0e88647c53c3837076340c8af5dd6e7d6eae1e979748907cc77735a2fa61fe3b5a03558b2e214bbd1e4f1066b9444fd27491b8cd594727b4df2c6c40a66ee092e48a04b8dd919d1cd6c0dc1c868e8b17383212a9291ee4c6129b74927822c836d96f580f90211a082dfa0895f58c8ab219b1a3495c930a91ced1024bb93d17db00e25b951a6c619a07daeef642e3fafcd93260f2c8486ee75803c32795ea83152752c7f298ba98481a0416d5ba0562c59a16a92991b267cdb40b25734856902f5599db0ebf64ce4ea40a006a001e9a09963a91a4e2fdea6a238d4b540699e8828085b460dab39744547c7a01dc72e0048890365d8fbfb7c5b1c8ef52d49e41e089d99f52fadffe3efde1303a0942505b8e8a3ec1f16bee602466ef6605139cce2b5802355aecd2de1def8363ba0096a2585a6d4d2912c5387d5998f22455a1baf48894c5f89621d22721202f238a0c798b5904ca51608776665eb627ba3a32ecb75eaf20cea825ece8f9b8a7a44f3a076f5e9f1ff4e8b68028f8dbf07711a9e5235887749da2db07d8c7ca23d1c06dba0019d4d8661b0e52876e58c1cb072c5c2aef8db86d35288be6ddbf6cd782eb5f6a01c418f5263baafdae54580467f5e50ec141611331f53db37d838c1671bc6a25ba0a0fb254b54da6444d91d0b6585c4a2fcdf9e19b10357377fd5699b4bad8adab6a00b841477da486c5819fd12285e8f097c92b317c9e239954f5cbba1c70f679b4ba0612b371378ad1d8cc5e0954a111df8e0c8ea0da63300ca1126fb1a54338b32f4a072a4f633843d50afdb0d3a76464892f1c392579ec74f6df6cf1df231ba4ab42ea07734e834476c826ab88df35eb30599174a9f863d17d18ce04f87f34526cb6fc480f90211a02fedb0b9b16e327962ff519dfc137fb4e25408054dc09c6cf8d97fcc8c58f1fca03869abaa6f82c34c1aba13cfe0b7ad104312b8ca918060c181dd406c8a99260ca0f753573922dd3666bd8c5dbd5b4ce6de8a8f0800188c034d383d8916a53ce3efa005613369534c7d926a4b06e352e6d17532bc802c0fcedd13073e68c41b99901da0c5daa0a98986bab70d997d7faa4b55ddbcb75bcf7cd71d7950d145222cb3e21fa02718fac0f09350134ea331146441ad6005f8a8c20b9673f5b4bb1d9cac9f2163a0895fe437ecebfb9a688f7de6f3e9ef5118168fc60d9eee552eb504d64d301f6fa0b4cf1ad7a7b3f08bc8842186fcd78ff7d746763fcae212432d0f20a50be4fb65a07396b72a68947b922b056495abe200f446a5fa9b01fd098d17a76a2672b9515ca09a877e342351f9e10dea0fbf7478ee67c215bfd821da88208b9fcf63bea39bfba0b5ead9f9ba5a3ac8c888cb19af13e8a3d279474818054d335b28e81c431cc72ea04e66c0882953c62e542817724480b4f8d7a7944b3dee7455b249be68b5b9990da03a1aca9f115f2d3d71ee1cc202c2129d6f72c4f80b7b85128d54f9be9cda8c2fa01c1a35b8aa431b2a845c34b464542a83220b17e4dd1a4d4774b1807f1f9c9e23a03b2492dac5c5619f8c84fc0969ff24f5695bb4363c22c4120c86d2bc128aabfaa0c30d11204878acb9ce6a7931150e9ec10f1a659076ec3c1528c663f1897f85e180f90211a043beb9ae278028ab0e6ae1dd97bfc1adc7da5d5b35418cde1372ed15dc60d844a0969897f77040974812fdc243499998d5a2f808b010e3e743fff5bb1cf06701b7a072a62f95c81d3849bc02102bcb66b5be775ad3b68cae7967451e6a13c48b6c43a0488199752a3a18aaaaa52b07d5a306826c4ccb2afe3cb30058de3e361dee74cfa0a63fb5ff17b1ca7f9c095cd9a888f4fd493a3379cdc2a0cfb49353c854923fc7a0ce7a2593ac4b8c89ad4c5fde8940d9695e969cfe6eb6a614954a48bcfd715843a0cb8b4d0264778a2ab04b96777ffe78a5ee62483a87446fceccb37813cda25b60a008fac15554b1c384ad91aa696e7e5e5454dc0c0fa343bb26b48a4f34ec95f785a0f1811154dd01ffd9f43443acd407e0beee53bbd03f40f63b7d993681182f0289a0a620126c5db0919a29b4b27c728dc42d2d63015849527be64acd0062b575c0eea088d3cde1a49a0ac95f076d1e15b3fde9cefd0f7e308f53b3aa466eb0385aec50a07f99a989d621bd1b59fa51d109f6413c9cb7f8ccd704dbf13cfb27bebec8f1b1a04321111d914057fe87d18e8c6f4128c6c7778fa2b73d435f0b2562c5910361a2a07ee88a697a560dc7023a840f16df54c599dc345e787927bf6628963e782a6847a078d58eb776d8d9dd6dbdbdd830b0350bd0427b15678ef457da5d41ec2cca708ca050e0c4585785b9c800e24c4c4e00599d7e5c4e6d8f3363979ab6c49ed514f12680f90211a011ff0a2d404fd7ed97509ebaa806f2a5ba09c5cde5ff596903c4313783487509a014931c578b05f5948939281aa31d2bc8b05b01c6932c45bf7a70972a430575c2a07272592f567daa667135799961e9eef529a6cd754395e39694d9452ae24a8797a092b17ad714173ec4787f0b3b9d2dfa96680861e093b5121441ffcde64183d074a06db41a6efb6f94c7d185f76deb8bb00468715bf6828fb63db31b880a6050c54da07ce695737ab0d4bf9003a06ce83b11e75d81fbeb47c013b41f9c2e00a97cb87aa0dfe63771f833e98a5aeff54d9dd5a8dcfd89ca43c23644b18ec8e29ab8ccc287a0a327c817dc8a8ea3a5d3ca3cb55169777a1bfa30fe9f0df842eb3978dbd6737ba053683114bdaed7819b30ab8baec1fb9a2a96fee4dabc72f319cec9869da3b0b0a04d98297a896312d18da40240ed9a527f4c01c73edd3ea1f7c28338d1d863d97ca070451b5f2a402b497659eb18e648ac46f39c0068cc91436eb0b082b1d06dd63da066e866f800200512b0d3e534c547f4d2012429152cc9693bf1553cc22361627ba003fc4e648aafdadd7a9fa7cb534103f08dc699413ecda22bda46898bfb792429a0b46a167c66b50c74227d03a68971e124fdd011d6c90f5a08f6fe30ae34de603ca0a7ced66271235bc27b154f37bee6d9a1366cd253176c96de707d124fcc593c35a0f4f09b104a86cefc5c282d393b415e6c224eb8a463386448ebebfad9f9f53c9680f90211a05f93540f4317a4c6d8b73556a7ffdab6fcf0aa36af84b8c4bd2a3e7114e2da4ea05dd8c13b1b83485911f5e1185669f7d5559c260193a72e52597a3e80736c248ca03d50a67e8ec93696c35865d9f03814e95406c8d04e5decc320b9a24e5beee1baa0a928e2ea8773ba69dde5344d69069b237667dbaaa69e86133d4e444e432799b1a0ebb2cbf0c3314ddf681f21a29fa17b320094684ba35e725bc36bbc407821cfa3a0762aeb8161d2b1b8a5ee51d1ede36f51cc2dad7e0c4d0ff097b89c831aff8c35a0957a8eaaac924688482d21a95b7a7f01889ab39a7a50d58efaaffa9e486ae071a046c10b0c15aa83973ea4b108f50bad2638941550fce7c9308c8b968abee271f8a08a831384faa68f9caa047a6200464e11cfe5f9f700a5ed9435e5241d9d2a501ca020630d0f41d1f38c61fc8d3fc6170f6f11fc52ade454930a3b5e4f4491b47467a04539a99793f29484fdbd39b606f27265499acb3c24461f48858655f07166f0dfa05fd40548cfae17d12e103db98572f22cdc8dd3ec670be570727a7ff68f6bce9fa032efe866f058f79ef06de75f682e10773576eb9fca3f950fda96ea9926784685a05c170d685d29417781f678b746174c7500e7c228b4bd71bcfe9f5421742a0b67a0c3fb71b77522f06c4a4e4cb7029e7faeb747b8e446460586ea0d5e9abae68cd9a03f2294bf8bea287c7afafde4b39aaa56716230ef425ece688f6a78fcadf5f49e80f9013180a0c2cb770a3d18eb1214a782cc81b79a7fd772716c2d050ef66011095c3774e8f7a08fc7d7da06fba7ffa69b095aae41147e3a55b89644682057cedab705ba7aefd5a05975b434f69398107a4d1729f8f56e75247df09c65b1a750797818607bf118df80a026cea4c13260b2a1dd74bb6fcc7cc36162d2856ce691a36165c633ba68f7b783a0f7b0c667509a4ce937c487b45bc53c0700543daf4f8c127fbe475b4e1084d2328080a0454eca3fcc32afd4c4000ccbb47732bbce342b1a9d374fb5872162f2c873625fa0b3e6c44579a731cc730a5472e83c6098fa2943e5b2c72f4475f0afea76848a87a03b8c951788b8c93366aedbf88f6c1ca6085cd0249025ce542f19294b40bb92f180a0a10cfa51ae290afebd64a5b530db7088fa0b02f22ce9b0838135b422b885dee5808080e482000ea07b2632b8b97e159d88f112a8dd9d44df2f3c4502e0c79a29297ea7f61f41f311f851a030590b16841225b9590cdc95b19176201d442ca0b931c6e4314d20a1c772ea9ba052e8f9f247cd159c65b304863d444087f6a60d7dbec3a0e4fa09f007b5a1c64f808080808080808080808080808080f86c9c20120c458c4c09a9448628f84e81161b308d5c4041a3d3a1ea329d0eb84df84b0487400e8b4f1c9c00a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47022440bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e22442465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c8162244295e26495cef6f69dfa69911d9d8e4f3bbadb89b977cf58294f7239d515e15b24cfeb82494056cf691eaf729b165f32c9757c429dba5051155903067e56ebe3698678e9122442d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab022443f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a224461dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d25224469c77a677c40c7fbea129d4b171a39b7a8ddabfab2317f59d86abfaf690850223d90e9e7593d91a29331dfc2f84d5adecc75fc39ecab4632c1b4400a3dd1e1298835bcca224472b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a5122447ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e22448b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d788694852244a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b7412244b218c5d6af1f979ac42bc68d98a5a0d796c6ab01b659ad0fbd9f515893fdd740b29ba0772dbde9b4635921dd91bd2963a0fc855e31f6338f45b211c4e9dedb7f2eb09de72244b4dd66d7c2c7e57f628210187192fb89d4b99dd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002244be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cd2244cc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a4192244d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce7392244e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d212244e9ae3261a475a27bb1028f140bc2a7c843318afd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002244ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c1921832244ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5b2244ef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd0756e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd02a440bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e2a4412d810c13e42811e9907c02e02d1fad46cfa18bab679cbab0276ac30ff5f198e5e1dedf6b84959129f70fe7a07fcdf13444ba45b5dbaa7b1f650adf8b0acbecd04e2675b2a442465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c8162a442d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab02a443f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a2a4461dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d252a4470f657164e5b75689b64b7fd1fa275f334f28e1896a26afa1295da81418593bd12814463d9f6e45c36a0e47eb4cd3e5b6af29c41e2a3a5636430155a466e216585af3ba72a4472b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a512a447ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e2a448b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d788694852a44a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b7412a44b4dd66d7c2c7e57f628210187192fb89d4b99dd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a44be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cd2a44cc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a4192a44d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce7392a44d93dbfb27e027f5e9e6da52b9e1c413ce35adc11b313f9cba57c63a84edb4079140e6dbd7829e5023c9532fce57e9fe602400a2953f4bf7dab66cca16e97be95d4de70442a44e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d212a44e9ae3261a475a27bb1028f140bc2a7c843318afd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a44ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c1921832a44ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5b2a44ef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd0756e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd0").to_vec(); + let mut any= hex!("0a282f6962632e6c69676874636c69656e74732e7061726c69612e76312e4d69736265686176696f757212cf370a0b78782d7061726c69612d3112de1b0ab4060ab106f9032ea0c3ca2cd851054700e22f8313521399aacfcc225541cde7dfeca894f9b57d7c22a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a0d269e8b47a345f3a77343f46943f78480a96ff82a8466963fb4a29c0e2b66091a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002820c1c8402625a0080846699bcdab90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b86086dcdfb683f4965de8062063dd843775eeb55a1271b317a6d65ef7aadabb1e10a9327c9face4c69c331b914f3b24aeb4010b30d4c4a7007c67d7de812e9c7cca598c9b3b1e94679e90aeb94b790b19dce6bee8662126eecdb3b539efee6468b7f848820c1aa049430f5e612a0b37a9bab1b1c5003f02f3586a4e2ea9e84d8de511f879f30561820c1ba0c3ca2cd851054700e22f8313521399aacfcc225541cde7dfeca894f9b57d7c22803135a7c114e967442e0bc0996b3b083aae7638e142b3a145b8d966267fecb84141fcf58023341e1aeaf333bfe4d91349db198c157947780f46b1d476a892c25900a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800ab4060ab106f9032ea02c07474042f3b317665fe4a233454a1ec921770d6429dd3eb0a23e812429d595a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a0d269e8b47a345f3a77343f46943f78480a96ff82a8466963fb4a29c0e2b66091a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002820c1d8402625a0080846699bcddb90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b860a410689613510c2087d762d49d42acb83f84b136e417e0567c8fbd693fd25cb36f794ae231b79101b94d700457f511120b7b2c8c0294c33b2d9728fa5d0a81a9c02901e28c3df1c840e7a4f7f6b5f150c3d7276b84a5f05d57a582ac6659692ff848820c1ba0c3ca2cd851054700e22f8313521399aacfcc225541cde7dfeca894f9b57d7c22820c1ca02c07474042f3b317665fe4a233454a1ec921770d6429dd3eb0a23e812429d59580dfca46ba06e40ca0191deacc05e2185acbfb04ca3ce23355f2b3d1be19667d096f33e5174260e4e5be857a49307dcf824f1b7e353c3be3e7bb4202c5bf4ae32b00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800ab4060ab106f9032ea0c0e82c0cda470def9ae9b03f55755b9cf0af015ae255bbb90a7969296918514aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a0d269e8b47a345f3a77343f46943f78480a96ff82a8466963fb4a29c0e2b66091a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002820c1e8402625a0080846699bce0b90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b860856d586a1618c0da1e906937b0a4c2596598a2d34e5cbf62063fc52ca9e5078fc962443b3a53166fabf69548b8d885ec08260a0d01293a3e61ba14d82e976f477f6ab2db2a8ae7c641cca0077c1770f472e7306ab43f8fecf762a95bc45ca1a5f848820c1ca02c07474042f3b317665fe4a233454a1ec921770d6429dd3eb0a23e812429d595820c1da0c0e82c0cda470def9ae9b03f55755b9cf0af015ae255bbb90a7969296918514a802a8efd919b1fe8bd679c8db7976de46350cfe3c2bdf67ec67e95c2f1c02909736bbb1bcdd798058072adc2e3cea6a16d519d1630e121539b8ccd77b1a7f84a1c00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180801203109b181a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0d8a8f0aaba741477e7d0c15b6a1759b3d842e346b35afd14219ecdd18188718ea0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a0bd63cc1cadd9ef7ffd41bb496484bff7c6ddbc3b29cf1a8b82d1f8f12bc6347680a0a74e307420bf9966d5db9a83ce48edc32c7a8e43328c6373de6875cefa04ad7aa0e502f113ade32bee3770b5a0117fa799c8812e5ab5a239e3878660c59c3537fda00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0d4182165b298d7b52b0f2064d19ab8bdad2b3955fa5b3d85c00673beb97e124480f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a03f47312ca98ac1f6ae9db9752c2a33529723b64e654d87f7847cee0382edfb55a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e56593428ee663799df81ea82bc8445a7d93c891ef324b5f4438eb766bcf75fc405fb79d3f618fcdd17f107b374368ef512f2244a7876ea32e7a748c697d01345145485561305b24903201f874819815e1a3f183c4addc814b71ec0e573e07f79ee9082926d82dd1711d6c45a9cc8841916d8563c2f80baa2a448fdaaa7e6631e438625ca25c857a3727ea28e56593428ee663799df81ea82bc8445a7d93c891ef324b5f4438eb766bcf75fc405fb79d3f618fcdd17f107b374368ef512f2a44d9a13701eafb76870cb220843b8c6476824bfa15a82968379b116362f75bdb7cc4be8ca0ceea7c0f2e74be").to_vec(); + let any2= hex!("7c8f289cda6dcbc5edbb26400e1306c2de06f52a9a583dab99300138011ade1b0ab4060ab106f9032ea0c3ca2cd851054700e22f8313521399aacfcc225541cde7dfeca894f9b57d7c22a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a0d269e8b47a345f3a77343f46943f78480a96ff82a8466963fb4a29c0e2b66091a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002820c1c8402625a0080846699bcdab90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b86086dcdfb683f4965de8062063dd843775eeb55a1271b317a6d65ef7aadabb1e10a9327c9face4c69c331b914f3b24aeb4010b30d4c4a7007c67d7de812e9c7cca598c9b3b1e94679e90aeb94b790b19dce6bee8662126eecdb3b539efee6468b7f848820c1aa049430f5e612a0b37a9bab1b1c5003f02f3586a4e2ea9e84d8de511f879f30561820c1ba0c3ca2cd851054700e22f8313521399aacfcc225541cde7dfeca894f9b57d7c22803135a7c114e967442e0bc0996b3b083aae7638e142b3a145b8d966267fecb84141fcf58023341e1aeaf333bfe4d91349db198c157947780f46b1d476a892c25900a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800ab4060ab106f9032ea02c07474042f3b317665fe4a233454a1ec921770d6429dd3eb0a23e812429d595a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a0d269e8b47a345f3a77343f46943f78480a96ff82a8466963fb4a29c0e2b66091a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002820c1d8402625a0080846699bcddb90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b860a410689613510c2087d762d49d42acb83f84b136e417e0567c8fbd693fd25cb36f794ae231b79101b94d700457f511120b7b2c8c0294c33b2d9728fa5d0a81a9c02901e28c3df1c840e7a4f7f6b5f150c3d7276b84a5f05d57a582ac6659692ff848820c1ba0c3ca2cd851054700e22f8313521399aacfcc225541cde7dfeca894f9b57d7c22820c1ca02c07474042f3b317665fe4a233454a1ec921770d6429dd3eb0a23e812429d59580dfca46ba06e40ca0191deacc05e2185acbfb04ca3ce23355f2b3d1be19667d096f33e5174260e4e5be857a49307dcf824f1b7e353c3be3e7bb4202c5bf4ae32b00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800ab4060ab106f9032ea0c0e82c0cda470def9ae9b03f55755b9cf0af015ae255bbb90a7969296918514aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a0d269e8b47a345f3a77343f46943f78480a96ff82a8466963fb4a29c0e2b66091a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002820c1e8402625a0080846699bce0b90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b860856d586a1618c0da1e906937b0a4c2596598a2d34e5cbf62063fc52ca9e5078fc962443b3a53166fabf69548b8d885ec08260a0d01293a3e61ba14d82e976f477f6ab2db2a8ae7c641cca0077c1770f472e7306ab43f8fecf762a95bc45ca1a5f848820c1ca02c07474042f3b317665fe4a233454a1ec921770d6429dd3eb0a23e812429d595820c1da0c0e82c0cda470def9ae9b03f55755b9cf0af015ae255bbb90a7969296918514a802a8efd919b1fe8bd679c8db7976de46350cfe3c2bdf67ec67e95c2f1c02909736bbb1bcdd798058072adc2e3cea6a16d519d1630e121539b8ccd77b1a7f84a1c00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180801203109b181a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0d8a8f0aaba741477e7d0c15b6a1759b3d842e346b35afd14219ecdd18188718ea0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a0bd63cc1cadd9ef7ffd41bb496484bff7c6ddbc3b29cf1a8b82d1f8f12bc6347680a0a74e307420bf9966d5db9a83ce48edc32c7a8e43328c6373de6875cefa04ad7aa0e502f113ade32bee3770b5a0117fa799c8812e5ab5a239e3878660c59c3537fda00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0d4182165b298d7b52b0f2064d19ab8bdad2b3955fa5b3d85c00673beb97e124480f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a03f47312ca98ac1f6ae9db9752c2a33529723b64e654d87f7847cee0382edfb55a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e56593428ee663799df81ea82bc8445a7d93c891ef324b5f4438eb766bcf75fc405fb79d3f618fcdd17f107b374368ef512f2244a7876ea32e7a748c697d01345145485561305b24903201f874819815e1a3f183c4addc814b71ec0e573e07f79ee9082926d82dd1711d6c45a9cc8841916d8563c2f80baa2a448fdaaa7e6631e438625ca25c857a3727ea28e56593428ee663799df81ea82bc8445a7d93c891ef324b5f4438eb766bcf75fc405fb79d3f618fcdd17f107b374368ef512f2a44d9a13701eafb76870cb220843b8c6476824bfa15a82968379b116362f75bdb7cc4be8ca0ceea7c0f2e74be7c8f289cda6dcbc5edbb26400e1306c2de06f52a9a583dab9930013801").to_vec(); any.extend(any2); let any: Any = any.try_into().unwrap(); // check if misbehavior let err = client .update_client(&ctx, client_id.clone(), any) .unwrap_err(); - assert!( - format!("{:?}", err).contains("UnexpectedSameBlockHash : 0-32160267"), - "{}", - err - ); + assert_err(err, "UnexpectedSameBlockHash : 0-3100"); // fail: invalid block let mut mock_consensus_state = BTreeMap::new(); let trusted_cs = ConsensusState { current_validators_hash: hex!( - "abe3670d5b312d3dd78123a31673e12413573eac5cada972eefb608edae91cac" + "5b514a7e8083146842c425a71aec83368ef4628442999a6d340d623ffb360c67" ), previous_validators_hash: hex!( - "dc895253030c1833d95cfaa05c9aac223222099bc4b86ab99eeab6021ba64a71" + "399334b2051da932262b42f25e5e59724c08df5c88d13c9d6bf5c51c33233aab" ), ..Default::default() }; - mock_consensus_state.insert(Height::new(0, 32160266), trusted_cs); + mock_consensus_state.insert(Height::new(0, 3354), trusted_cs); let ctx = MockClientReader { client_state: Some(ClientState { - chain_id: mainnet(), + chain_id: ChainId::new(9999), ..Default::default() }), consensus_state: mock_consensus_state.clone(), }; - let mut any = hex!("0a282f6962632e6c69676874636c69656e74732e7061726c69612e76312e4d69736265686176696f757212898e010a0b78782d7061726c69612d3112fb460a9d060a9a06f90317a0a253fa96c80a63c58a92c2169edc61d58f53912fbecf0a3d23d95ddd7d375b1aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479469c77a677c40c7fbea129d4b171a39b7a8ddabfaa0367319f8df31ff4b616b09c5d0877147904002cbeb93701e2bc2291d3f85e373a0a36d378b3813df6d2cfb735f98b9f1c2ad274767d70d2b83f01df65bd7060c7da0c07110486e8eb7be3528220485458e1904554e77a709835bcdf102de08b61445b901004222e610319851925ec8a154c538000d1618a08003578c18285805003b321c97a7345044c970940be2052cba00125380a2085c53144f23627c415c3349272ee714926a41234418b9af7c04bda5080931a51709a3547d9f82a30db42080012c05016881359b46c3820001bc98e1428bdb2c590c6f88418c3d70c47a1048c8a48934bdb1342c0b5c54808ca48044270ceb88a536f54270754b07051c489bc4f02586c0841997d889a8243816842b8b2498200a90d518a8c78213412a2c515b446c2584150775092b9286a6202b8846f2812415a35019ee011433114cfea021f67e431a0305206470020364a623a020894870960ea0c2764e4b95ca4e10238b10a9028401eaba0b8408583b0083ad346e846516831eb90118d98301020b846765746889676f312e31392e3132856c696e75780000b19df4a2f8b5831defffb86081828df4756db11e725568e085da9ea4f1db63f97645e76c91f77d22ffef7200e0a8f06d9f2f2698f62d99c972c488ba009b507f36b346254e782534110e04a20772e2dd6a2ba12f482b478cfada1981fb46fe33d31a08ebef4abaa4ac2b83fcf84c8401eaba09a03009339cf4323f2c5efd3ec22eeb696e0b0a4e6ab60ed9f9d4c8f23bf227ac7a8401eaba0aa0a253fa96c80a63c58a92c2169edc61d58f53912fbecf0a3d23d95ddd7d375b1a8083ad988504ae27211e4a676510c51568f555d6b95545410b209b6761282cd3e679e277a8969b5f5d97101ae220174d69e960ce9f13bf7fdf0661c368b1df347400a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a0ec996d8163dd118f6fa5e2a83a7d19fe665a2317facaa7ae9fbc95e6aca7e7cca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479472b61c6014342d914470ec7ac2975be345796c2ba0d4d38d061e7a8eaa7beaf72bfda8e61ab5bf52aea4315b273e29a7bdccef7cb8a0087324763ee1c00c9ad8d09121f2d2f56d80d593342bcd998e4fca26f0e03153a05eea513d92cac961941b786a8827e4d1375885b0cbb90af62fca8e0fd9285ed3b901008d6b62622b1c923e0b335b6584226a3b955878d0deba0ec87a78e16a316a2034876953d9d2a6e610c7b1faa45f9e6f6381e1c118207bbaa650282513dd3c2edc0cd7c42ebf6acc6e21ad284b7724473d2675b0224fd6e2bcb1b64eb490b0cf294f3fb9755b072fad587b8b7881341f08fc157c55c23a543e2f65949e4fbba4c5f5daa92c0eaf839b9d8ae4888d026c1eb46cd4edb96a619a1a1584f8f4ac0f2402d2b9857249930c8528f166ee9e4e59c18210453d06b1874d31a82a05f678abe04a1e9a98811d5fd6a848ed024c78b0a6fba25c9a42e6361513510e79aaeea810d1d805d4e0db90c90b2a92530081e349946b6893bc8079f17746207c3d1158028401eaba0c84084fe2c683efb91f8465168321b90118d88301020b846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5831defffb86083265457e59114983f1076e6afe3914e8f6c68afcb50c434f49e3d4f3e380208adde4d348c10d83a4caa577dc8f875050aace673b180818bc9c53c44be471a089d2773a9088356409b7668f24e0221f5dc0e12d121552cf2554a54710fde149df84c8401eaba0aa0a253fa96c80a63c58a92c2169edc61d58f53912fbecf0a3d23d95ddd7d375b1a8401eaba0ba0ec996d8163dd118f6fa5e2a83a7d19fe665a2317facaa7ae9fbc95e6aca7e7cc80fea86520fb3bdd71a0744ae6311c632107f640536f647f352c4d76cdefc0fe3f334095862d3f08362d50104caa4dcae5f15cb24a25a6e7c413ad04b20e7d6d1901a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a0937afa96827a173a5ab83721cc146cb8f10dc87ba31ceff7e2395d2589a904dba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e2d3a739effcd3a99387d015e260eefac72ebea1a0711c94607e53ea254337a19dfe928741d406c0217becb0b51034fc91a4b2e88ea0e540e2e257a6edbb482543f15e1690410b70cddc7b8111f48de4c688a35caca1a0ded39245b638233ed2ac16389abb608f6329d48557888cd16de33d6b510873f6b901000e220e06afc4d15833201a459150012f1a51400005088c06383961403a2c0c00a42c3111001898020123ecf3081a00838e000418000b60a00490a002003f2a014458d8408570580b0148802b24a00428a132222861f47b86248404b4c02316210b2c802b0aa209d500c98d000145090d38c84409084cc420b944593410ca38a2c83c80a40b38108af0d84420240404fa2a740e812ca604ba38819241410b9070060182011f801211019aa03c0b8004a31c8b47204a0e450812f803a206402260a40b971220084c065500489b50315423a0402510d52900144513444e1421ed5d1511a45d1822275801b522040090017126448c05132a04e85608991043990849018401eaba0d84085832a78389fc6a8465168324b90118d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a2f8b5831defffb860accd42f5a790b23a42c750634bd4c632b68b4a13d9e67a23fc88e634c1f5be8b8824355e90f5e6bcb23af9f0ecdb041c011c645770184427d940f1078c0f20aa6f70aa3e68944f9e588ec0726febd32ab6519295e3eefdfd66ca3ff0a57e6e3af84c8401eaba0ba0ec996d8163dd118f6fa5e2a83a7d19fe665a2317facaa7ae9fbc95e6aca7e7cc8401eaba0ca0937afa96827a173a5ab83721cc146cb8f10dc87ba31ceff7e2395d2589a904db80c68c3a1187742f4228a35df126397c068f0d529182962a834f230031471c12bc6d4cc917d21556160579a782e799fdbce7d5bae9c67027ac6f9860f540f768db00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000801205108af4aa0f1a951df90e92f90211a02bff590463eb4f2fb98586805a6591c49ad02eb38211ce40238beef315d2b1a3a03f20d9b30890c082262b4ebcb9c089af0b95a18873fd3c0b1a13e0d0c71137eba0c0649e9f0a6040129bcd329483228eba044da097d400621ab85b5351d2980b40a0304852b72a4c75c7d71e3946ef983cf4c1f3c2b478c8997870a1d4454ae04dbfa0432d943bbfe2b6d9f62df84439769f8ea76f9213c6fcfdcf2052d5c31dcdf16fa00c4d39f0619caa3ae86e99de2395b94ba29a52ab6e4966a5bb4b138ae39e0c70a0384ee242954ec95a8f3372527b557488894506ab1a9fe80fc8381ff15216e103a022bb93d7f4851836b855b2570e2e01270585595c9792cc4e93a437a4e474bb5fa0d02fec5b104fcc8919ab37aff38a323fb06bb05663078b901c7dd54306d3caeda0f18f265a00fedc81f65cde8e79d8909c9eaf01cb1badafac441193c3911a50cfa0a475a4d413336a0497c6c412db1f4a0b75339d8ebaa318ead92b01926f904668a08b350addc0ac0af1c475f6ea8c89f9e7bfd2f08db1496d88a4b9b8d7e68b775ca0a93aa453df1f6fea8e6586b761752c988bebc9d8919fce66a2dc07b13b516317a0e88647c53c3837076340c8af5dd6e7d6eae1e979748907cc77735a2fa61fe3b5a03558b2e214bbd1e4f1066b9444fd27491b8cd594727b4df2c6c40a66ee092e48a04b8dd919d1cd6c0dc1c868e8b17383212a9291ee4c6129b74927822c836d96f580f90211a082dfa0895f58c8ab219b1a3495c930a91ced1024bb93d17db00e25b951a6c619a07daeef642e3fafcd93260f2c8486ee75803c32795ea83152752c7f298ba98481a0416d5ba0562c59a16a92991b267cdb40b25734856902f5599db0ebf64ce4ea40a006a001e9a09963a91a4e2fdea6a238d4b540699e8828085b460dab39744547c7a01dc72e0048890365d8fbfb7c5b1c8ef52d49e41e089d99f52fadffe3efde1303a0942505b8e8a3ec1f16bee602466ef6605139cce2b5802355aecd2de1def8363ba0096a2585a6d4d2912c5387d5998f22455a1baf48894c5f89621d22721202f238a0c798b5904ca51608776665eb627ba3a32ecb75eaf20cea825ece8f9b8a7a44f3a076f5e9f1ff4e8b68028f8dbf07711a9e5235887749da2db07d8c7ca23d1c06dba0019d4d8661b0e52876e58c1cb072c5c2aef8db86d35288be6ddbf6cd782eb5f6a01c418f5263baafdae54580467f5e50ec141611331f53db37d838c1671bc6a25ba0a0fb254b54da6444d91d0b6585c4a2fcdf9e19b10357377fd5699b4bad8adab6a00b841477da486c5819fd12285e8f097c92b317c9e239954f5cbba1c70f679b4ba0612b371378ad1d8cc5e0954a111df8e0c8ea0da63300ca1126fb1a54338b32f4a072a4f633843d50afdb0d3a76464892f1c392579ec74f6df6cf1df231ba4ab42ea07734e834476c826ab88df35eb30599174a9f863d17d18ce04f87f34526cb6fc480f90211a02fedb0b9b16e327962ff519dfc137fb4e25408054dc09c6cf8d97fcc8c58f1fca03869abaa6f82c34c1aba13cfe0b7ad104312b8ca918060c181dd406c8a99260ca0f753573922dd3666bd8c5dbd5b4ce6de8a8f0800188c034d383d8916a53ce3efa005613369534c7d926a4b06e352e6d17532bc802c0fcedd13073e68c41b99901da0c5daa0a98986bab70d997d7faa4b55ddbcb75bcf7cd71d7950d145222cb3e21fa02718fac0f09350134ea331146441ad6005f8a8c20b9673f5b4bb1d9cac9f2163a0895fe437ecebfb9a688f7de6f3e9ef5118168fc60d9eee552eb504d64d301f6fa0b4cf1ad7a7b3f08bc8842186fcd78ff7d746763fcae212432d0f20a50be4fb65a07396b72a68947b922b056495abe200f446a5fa9b01fd098d17a76a2672b9515ca09a877e342351f9e10dea0fbf7478ee67c215bfd821da88208b9fcf63bea39bfba0b5ead9f9ba5a3ac8c888cb19af13e8a3d279474818054d335b28e81c431cc72ea04e66c0882953c62e542817724480b4f8d7a7944b3dee7455b249be68b5b9990da03a1aca9f115f2d3d71ee1cc202c2129d6f72c4f80b7b85128d54f9be9cda8c2fa01c1a35b8aa431b2a845c34b464542a83220b17e4dd1a4d4774b1807f1f9c9e23a03b2492dac5c5619f8c84fc0969ff24f5695bb4363c22c4120c86d2bc128aabfaa0c30d11204878acb9ce6a7931150e9ec10f1a659076ec3c1528c663f1897f85e180f90211a043beb9ae278028ab0e6ae1dd97bfc1adc7da5d5b35418cde1372ed15dc60d844a0969897f77040974812fdc243499998d5a2f808b010e3e743fff5bb1cf06701b7a072a62f95c81d3849bc02102bcb66b5be775ad3b68cae7967451e6a13c48b6c43a0488199752a3a18aaaaa52b07d5a306826c4ccb2afe3cb30058de3e361dee74cfa0a63fb5ff17b1ca7f9c095cd9a888f4fd493a3379cdc2a0cfb49353c854923fc7a0ce7a2593ac4b8c89ad4c5fde8940d9695e969cfe6eb6a614954a48bcfd715843a0cb8b4d0264778a2ab04b96777ffe78a5ee62483a87446fceccb37813cda25b60a008fac15554b1c384ad91aa696e7e5e5454dc0c0fa343bb26b48a4f34ec95f785a0f1811154dd01ffd9f43443acd407e0beee53bbd03f40f63b7d993681182f0289a0a620126c5db0919a29b4b27c728dc42d2d63015849527be64acd0062b575c0eea088d3cde1a49a0ac95f076d1e15b3fde9cefd0f7e308f53b3aa466eb0385aec50a07f99a989d621bd1b59fa51d109f6413c9cb7f8ccd704dbf13cfb27bebec8f1b1a04321111d914057fe87d18e8c6f4128c6c7778fa2b73d435f0b2562c5910361a2a07ee88a697a560dc7023a840f16df54c599dc345e787927bf6628963e782a6847a078d58eb776d8d9dd6dbdbdd830b0350bd0427b15678ef457da5d41ec2cca708ca050e0c4585785b9c800e24c4c4e00599d7e5c4e6d8f3363979ab6c49ed514f12680f90211a011ff0a2d404fd7ed97509ebaa806f2a5ba09c5cde5ff596903c4313783487509a014931c578b05f5948939281aa31d2bc8b05b01c6932c45bf7a70972a430575c2a07272592f567daa667135799961e9eef529a6cd754395e39694d9452ae24a8797a092b17ad714173ec4787f0b3b9d2dfa96680861e093b5121441ffcde64183d074a06db41a6efb6f94c7d185f76deb8bb00468715bf6828fb63db31b880a6050c54da07ce695737ab0d4bf9003a06ce83b11e75d81fbeb47c013b41f9c2e00a97cb87aa0dfe63771f833e98a5aeff54d9dd5a8dcfd89ca43c23644b18ec8e29ab8ccc287a0a327c817dc8a8ea3a5d3ca3cb55169777a1bfa30fe9f0df842eb3978dbd6737ba053683114bdaed7819b30ab8baec1fb9a2a96fee4dabc72f319cec9869da3b0b0a04d98297a896312d18da40240ed9a527f4c01c73edd3ea1f7c28338d1d863d97ca070451b5f2a402b497659eb18e648ac46f39c0068cc91436eb0b082b1d06dd63da066e866f800200512b0d3e534c547f4d2012429152cc9693bf1553cc22361627ba003fc4e648aafdadd7a9fa7cb534103f08dc699413ecda22bda46898bfb792429a0b46a167c66b50c74227d03a68971e124fdd011d6c90f5a08f6fe30ae34de603ca0a7ced66271235bc27b154f37bee6d9a1366cd253176c96de707d124fcc593c35a0f4f09b104a86cefc5c282d393b415e6c224eb8a463386448ebebfad9f9f53c9680f90211a05f93540f4317a4c6d8b73556a7ffdab6fcf0aa36af84b8c4bd2a3e7114e2da4ea05dd8c13b1b83485911f5e1185669f7d5559c260193a72e52597a3e80736c248ca03d50a67e8ec93696c35865d9f03814e95406c8d04e5decc320b9a24e5beee1baa0a928e2ea8773ba69dde5344d69069b237667dbaaa69e86133d4e444e432799b1a0ebb2cbf0c3314ddf681f21a29fa17b320094684ba35e725bc36bbc407821cfa3a0762aeb8161d2b1b8a5ee51d1ede36f51cc2dad7e0c4d0ff097b89c831aff8c35a0957a8eaaac924688482d21a95b7a7f01889ab39a7a50d58efaaffa9e486ae071a046c10b0c15aa83973ea4b108f50bad2638941550fce7c9308c8b968abee271f8a08a831384faa68f9caa047a6200464e11cfe5f9f700a5ed9435e5241d9d2a501ca020630d0f41d1f38c61fc8d3fc6170f6f11fc52ade454930a3b5e4f4491b47467a04539a99793f29484fdbd39b606f27265499acb3c24461f48858655f07166f0dfa05fd40548cfae17d12e103db98572f22cdc8dd3ec670be570727a7ff68f6bce9fa032efe866f058f79ef06de75f682e10773576eb9fca3f950fda96ea9926784685a05c170d685d29417781f678b746174c7500e7c228b4bd71bcfe9f5421742a0b67a0c3fb71b77522f06c4a4e4cb7029e7faeb747b8e446460586ea0d5e9abae68cd9a03f2294bf8bea287c7afafde4b39aaa56716230ef425ece688f6a78fcadf5f49e80f9013180a0c2cb770a3d18eb1214a782cc81b79a7fd772716c2d050ef66011095c3774e8f7a08fc7d7da06fba7ffa69b095aae41147e3a55b89644682057cedab705ba7aefd5a05975b434f69398107a4d1729f8f56e75247df09c65b1a750797818607bf118df80a026cea4c13260b2a1dd74bb6fcc7cc36162d2856ce691a36165c633ba68f7b783a0f7b0c667509a4ce937c487b45bc53c0700543daf4f8c127fbe475b4e1084d2328080a0454eca3fcc32afd4c4000ccbb47732bbce342b1a9d374fb5872162f2c873625fa0b3e6c44579a731cc730a5472e83c6098fa2943e5b2c72f4475f0afea76848a87a03b8c951788b8c93366aedbf88f6c1ca6085cd0249025ce542f19294b40bb92f180a0a10cfa51ae290afebd64a5b530db7088fa0b02f22ce9b0838135b422b885dee5808080e482000ea07b2632b8b97e159d88f112a8dd9d44df2f3c4502e0c79a29297ea7f61f41f311f851a030590b16841225b9590cdc95b19176201d442ca0b931c6e4314d20a1c772ea9ba052e8f9f247cd159c65b304863d444087f6a60d7dbec3a0e4fa09f007b5a1c64f808080808080808080808080808080f86c9c20120c458c4c09a9448628f84e81161b308d5c4041a3d3a1ea329d0eb84df84b0487400e8b4f1c9c00a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47022440bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e22442465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c8162244295e26495cef6f69dfa69911d9d8e4f3bbadb89b977cf58294f7239d515e15b24cfeb82494056cf691eaf729b165f32c9757c429dba5051155903067e56ebe3698678e9122442d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab022443f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a224461dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d25224469c77a677c40c7fbea129d4b171a39b7a8ddabfab2317f59d86abfaf690850223d90e9e7593d91a29331dfc2f84d5adecc75fc39ecab4632c1b4400a3dd1e1298835bcca224472b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a5122447ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e22448b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d788694852244a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b7412244b218c5d6af1f979ac42bc68d98a5a0d796c6ab01b659ad0fbd9f515893fdd740b29ba0772dbde9b4635921dd91bd2963a0fc855e31f6338f45b211c4e9dedb7f2eb09de72244b4dd66d7c2c7e57f628210187192fb89d4b99dd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002244be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cd2244cc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a4192244d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce7392244e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d212244e9ae3261a475a27bb1028f140bc2a7c843318afd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002244ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c1921832244ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5b2244ef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd0756e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd02a440bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e2a4412d810c13e42811e9907c02e02d1fad46cfa18bab679cbab0276ac30ff5f198e5e1dedf6b84959129f70fe7a07fcdf13444ba45b5dbaa7b1f650adf8b0acbecd04e2675b2a442465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c8162a442d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab02a443f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a2a4461dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d252a4470f657164e5b75689b64b7fd1fa275f334f28e1896a26afa1295da81418593bd12814463d9f6e45c36a0e47eb4cd3e5b6af29c41e2a3a5636430155a466e216585af3ba72a4472b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a512a447ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e2a448b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d788694852a44a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b7412a44b4dd66d7c2c7e57f628210187192fb89d4b99dd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a44be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cd2a44cc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a4192a44d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce7392a44d93dbfb27e027f5e9e6da52b9e1c413ce35adc11b313f9cba57c63a84edb4079140e6dbd7829e5023c9532fce57e9fe602400a2953f4bf7dab66cca16e97be95d4de70442a44e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d212a44e9ae3261a475a27bb1028f140bc2a7c843318afd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a44ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c1921832a44ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5b2a44ef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd075").to_vec(); - let any2 = hex!("6e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd01afb460a9d060a9a06f90317a0a253fa96c80a63c58a92c2169edc61d58f53912fbecf0a3d23d95ddd7d375b1aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479469c77a677c40c7fbea129d4b171a39b7a8ddabfaa00000000000000000000000000000000000000000000000000000000000000000a0a36d378b3813df6d2cfb735f98b9f1c2ad274767d70d2b83f01df65bd7060c7da0c07110486e8eb7be3528220485458e1904554e77a709835bcdf102de08b61445b901004222e610319851925ec8a154c538000d1618a08003578c18285805003b321c97a7345044c970940be2052cba00125380a2085c53144f23627c415c3349272ee714926a41234418b9af7c04bda5080931a51709a3547d9f82a30db42080012c05016881359b46c3820001bc98e1428bdb2c590c6f88418c3d70c47a1048c8a48934bdb1342c0b5c54808ca48044270ceb88a536f54270754b07051c489bc4f02586c0841997d889a8243816842b8b2498200a90d518a8c78213412a2c515b446c2584150775092b9286a6202b8846f2812415a35019ee011433114cfea021f67e431a0305206470020364a623a020894870960ea0c2764e4b95ca4e10238b10a9028401eaba0b8408583b0083ad346e846516831eb90118d98301020b846765746889676f312e31392e3132856c696e75780000b19df4a2f8b5831defffb86081828df4756db11e725568e085da9ea4f1db63f97645e76c91f77d22ffef7200e0a8f06d9f2f2698f62d99c972c488ba009b507f36b346254e782534110e04a20772e2dd6a2ba12f482b478cfada1981fb46fe33d31a08ebef4abaa4ac2b83fcf84c8401eaba09a03009339cf4323f2c5efd3ec22eeb696e0b0a4e6ab60ed9f9d4c8f23bf227ac7a8401eaba0aa0a253fa96c80a63c58a92c2169edc61d58f53912fbecf0a3d23d95ddd7d375b1a8083ad988504ae27211e4a676510c51568f555d6b95545410b209b6761282cd3e679e277a8969b5f5d97101ae220174d69e960ce9f13bf7fdf0661c368b1df347400a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a0ec996d8163dd118f6fa5e2a83a7d19fe665a2317facaa7ae9fbc95e6aca7e7cca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479472b61c6014342d914470ec7ac2975be345796c2ba0d4d38d061e7a8eaa7beaf72bfda8e61ab5bf52aea4315b273e29a7bdccef7cb8a0087324763ee1c00c9ad8d09121f2d2f56d80d593342bcd998e4fca26f0e03153a05eea513d92cac961941b786a8827e4d1375885b0cbb90af62fca8e0fd9285ed3b901008d6b62622b1c923e0b335b6584226a3b955878d0deba0ec87a78e16a316a2034876953d9d2a6e610c7b1faa45f9e6f6381e1c118207bbaa650282513dd3c2edc0cd7c42ebf6acc6e21ad284b7724473d2675b0224fd6e2bcb1b64eb490b0cf294f3fb9755b072fad587b8b7881341f08fc157c55c23a543e2f65949e4fbba4c5f5daa92c0eaf839b9d8ae4888d026c1eb46cd4edb96a619a1a1584f8f4ac0f2402d2b9857249930c8528f166ee9e4e59c18210453d06b1874d31a82a05f678abe04a1e9a98811d5fd6a848ed024c78b0a6fba25c9a42e6361513510e79aaeea810d1d805d4e0db90c90b2a92530081e349946b6893bc8079f17746207c3d1158028401eaba0c84084fe2c683efb91f8465168321b90118d88301020b846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5831defffb86083265457e59114983f1076e6afe3914e8f6c68afcb50c434f49e3d4f3e380208adde4d348c10d83a4caa577dc8f875050aace673b180818bc9c53c44be471a089d2773a9088356409b7668f24e0221f5dc0e12d121552cf2554a54710fde149df84c8401eaba0aa0a253fa96c80a63c58a92c2169edc61d58f53912fbecf0a3d23d95ddd7d375b1a8401eaba0ba0ec996d8163dd118f6fa5e2a83a7d19fe665a2317facaa7ae9fbc95e6aca7e7cc80fea86520fb3bdd71a0744ae6311c632107f640536f647f352c4d76cdefc0fe3f334095862d3f08362d50104caa4dcae5f15cb24a25a6e7c413ad04b20e7d6d1901a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a0937afa96827a173a5ab83721cc146cb8f10dc87ba31ceff7e2395d2589a904dba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e2d3a739effcd3a99387d015e260eefac72ebea1a0711c94607e53ea254337a19dfe928741d406c0217becb0b51034fc91a4b2e88ea0e540e2e257a6edbb482543f15e1690410b70cddc7b8111f48de4c688a35caca1a0ded39245b638233ed2ac16389abb608f6329d48557888cd16de33d6b510873f6b901000e220e06afc4d15833201a459150012f1a51400005088c06383961403a2c0c00a42c3111001898020123ecf3081a00838e000418000b60a00490a002003f2a014458d8408570580b0148802b24a00428a132222861f47b86248404b4c02316210b2c802b0aa209d500c98d000145090d38c84409084cc420b944593410ca38a2c83c80a40b38108af0d84420240404fa2a740e812ca604ba38819241410b9070060182011f801211019aa03c0b8004a31c8b47204a0e450812f803a206402260a40b971220084c065500489b50315423a0402510d52900144513444e1421ed5d1511a45d1822275801b522040090017126448c05132a04e85608991043990849018401eaba0d84085832a78389fc6a8465168324b90118d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a2f8b5831defffb860accd42f5a790b23a42c750634bd4c632b68b4a13d9e67a23fc88e634c1f5be8b8824355e90f5e6bcb23af9f0ecdb041c011c645770184427d940f1078c0f20aa6f70aa3e68944f9e588ec0726febd32ab6519295e3eefdfd66ca3ff0a57e6e3af84c8401eaba0ba0ec996d8163dd118f6fa5e2a83a7d19fe665a2317facaa7ae9fbc95e6aca7e7cc8401eaba0ca0937afa96827a173a5ab83721cc146cb8f10dc87ba31ceff7e2395d2589a904db80c68c3a1187742f4228a35df126397c068f0d529182962a834f230031471c12bc6d4cc917d21556160579a782e799fdbce7d5bae9c67027ac6f9860f540f768db00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000801205108af4aa0f1a951df90e92f90211a02bff590463eb4f2fb98586805a6591c49ad02eb38211ce40238beef315d2b1a3a03f20d9b30890c082262b4ebcb9c089af0b95a18873fd3c0b1a13e0d0c71137eba0c0649e9f0a6040129bcd329483228eba044da097d400621ab85b5351d2980b40a0304852b72a4c75c7d71e3946ef983cf4c1f3c2b478c8997870a1d4454ae04dbfa0432d943bbfe2b6d9f62df84439769f8ea76f9213c6fcfdcf2052d5c31dcdf16fa00c4d39f0619caa3ae86e99de2395b94ba29a52ab6e4966a5bb4b138ae39e0c70a0384ee242954ec95a8f3372527b557488894506ab1a9fe80fc8381ff15216e103a022bb93d7f4851836b855b2570e2e01270585595c9792cc4e93a437a4e474bb5fa0d02fec5b104fcc8919ab37aff38a323fb06bb05663078b901c7dd54306d3caeda0f18f265a00fedc81f65cde8e79d8909c9eaf01cb1badafac441193c3911a50cfa0a475a4d413336a0497c6c412db1f4a0b75339d8ebaa318ead92b01926f904668a08b350addc0ac0af1c475f6ea8c89f9e7bfd2f08db1496d88a4b9b8d7e68b775ca0a93aa453df1f6fea8e6586b761752c988bebc9d8919fce66a2dc07b13b516317a0e88647c53c3837076340c8af5dd6e7d6eae1e979748907cc77735a2fa61fe3b5a03558b2e214bbd1e4f1066b9444fd27491b8cd594727b4df2c6c40a66ee092e48a04b8dd919d1cd6c0dc1c868e8b17383212a9291ee4c6129b74927822c836d96f580f90211a082dfa0895f58c8ab219b1a3495c930a91ced1024bb93d17db00e25b951a6c619a07daeef642e3fafcd93260f2c8486ee75803c32795ea83152752c7f298ba98481a0416d5ba0562c59a16a92991b267cdb40b25734856902f5599db0ebf64ce4ea40a006a001e9a09963a91a4e2fdea6a238d4b540699e8828085b460dab39744547c7a01dc72e0048890365d8fbfb7c5b1c8ef52d49e41e089d99f52fadffe3efde1303a0942505b8e8a3ec1f16bee602466ef6605139cce2b5802355aecd2de1def8363ba0096a2585a6d4d2912c5387d5998f22455a1baf48894c5f89621d22721202f238a0c798b5904ca51608776665eb627ba3a32ecb75eaf20cea825ece8f9b8a7a44f3a076f5e9f1ff4e8b68028f8dbf07711a9e5235887749da2db07d8c7ca23d1c06dba0019d4d8661b0e52876e58c1cb072c5c2aef8db86d35288be6ddbf6cd782eb5f6a01c418f5263baafdae54580467f5e50ec141611331f53db37d838c1671bc6a25ba0a0fb254b54da6444d91d0b6585c4a2fcdf9e19b10357377fd5699b4bad8adab6a00b841477da486c5819fd12285e8f097c92b317c9e239954f5cbba1c70f679b4ba0612b371378ad1d8cc5e0954a111df8e0c8ea0da63300ca1126fb1a54338b32f4a072a4f633843d50afdb0d3a76464892f1c392579ec74f6df6cf1df231ba4ab42ea07734e834476c826ab88df35eb30599174a9f863d17d18ce04f87f34526cb6fc480f90211a02fedb0b9b16e327962ff519dfc137fb4e25408054dc09c6cf8d97fcc8c58f1fca03869abaa6f82c34c1aba13cfe0b7ad104312b8ca918060c181dd406c8a99260ca0f753573922dd3666bd8c5dbd5b4ce6de8a8f0800188c034d383d8916a53ce3efa005613369534c7d926a4b06e352e6d17532bc802c0fcedd13073e68c41b99901da0c5daa0a98986bab70d997d7faa4b55ddbcb75bcf7cd71d7950d145222cb3e21fa02718fac0f09350134ea331146441ad6005f8a8c20b9673f5b4bb1d9cac9f2163a0895fe437ecebfb9a688f7de6f3e9ef5118168fc60d9eee552eb504d64d301f6fa0b4cf1ad7a7b3f08bc8842186fcd78ff7d746763fcae212432d0f20a50be4fb65a07396b72a68947b922b056495abe200f446a5fa9b01fd098d17a76a2672b9515ca09a877e342351f9e10dea0fbf7478ee67c215bfd821da88208b9fcf63bea39bfba0b5ead9f9ba5a3ac8c888cb19af13e8a3d279474818054d335b28e81c431cc72ea04e66c0882953c62e542817724480b4f8d7a7944b3dee7455b249be68b5b9990da03a1aca9f115f2d3d71ee1cc202c2129d6f72c4f80b7b85128d54f9be9cda8c2fa01c1a35b8aa431b2a845c34b464542a83220b17e4dd1a4d4774b1807f1f9c9e23a03b2492dac5c5619f8c84fc0969ff24f5695bb4363c22c4120c86d2bc128aabfaa0c30d11204878acb9ce6a7931150e9ec10f1a659076ec3c1528c663f1897f85e180f90211a043beb9ae278028ab0e6ae1dd97bfc1adc7da5d5b35418cde1372ed15dc60d844a0969897f77040974812fdc243499998d5a2f808b010e3e743fff5bb1cf06701b7a072a62f95c81d3849bc02102bcb66b5be775ad3b68cae7967451e6a13c48b6c43a0488199752a3a18aaaaa52b07d5a306826c4ccb2afe3cb30058de3e361dee74cfa0a63fb5ff17b1ca7f9c095cd9a888f4fd493a3379cdc2a0cfb49353c854923fc7a0ce7a2593ac4b8c89ad4c5fde8940d9695e969cfe6eb6a614954a48bcfd715843a0cb8b4d0264778a2ab04b96777ffe78a5ee62483a87446fceccb37813cda25b60a008fac15554b1c384ad91aa696e7e5e5454dc0c0fa343bb26b48a4f34ec95f785a0f1811154dd01ffd9f43443acd407e0beee53bbd03f40f63b7d993681182f0289a0a620126c5db0919a29b4b27c728dc42d2d63015849527be64acd0062b575c0eea088d3cde1a49a0ac95f076d1e15b3fde9cefd0f7e308f53b3aa466eb0385aec50a07f99a989d621bd1b59fa51d109f6413c9cb7f8ccd704dbf13cfb27bebec8f1b1a04321111d914057fe87d18e8c6f4128c6c7778fa2b73d435f0b2562c5910361a2a07ee88a697a560dc7023a840f16df54c599dc345e787927bf6628963e782a6847a078d58eb776d8d9dd6dbdbdd830b0350bd0427b15678ef457da5d41ec2cca708ca050e0c4585785b9c800e24c4c4e00599d7e5c4e6d8f3363979ab6c49ed514f12680f90211a011ff0a2d404fd7ed97509ebaa806f2a5ba09c5cde5ff596903c4313783487509a014931c578b05f5948939281aa31d2bc8b05b01c6932c45bf7a70972a430575c2a07272592f567daa667135799961e9eef529a6cd754395e39694d9452ae24a8797a092b17ad714173ec4787f0b3b9d2dfa96680861e093b5121441ffcde64183d074a06db41a6efb6f94c7d185f76deb8bb00468715bf6828fb63db31b880a6050c54da07ce695737ab0d4bf9003a06ce83b11e75d81fbeb47c013b41f9c2e00a97cb87aa0dfe63771f833e98a5aeff54d9dd5a8dcfd89ca43c23644b18ec8e29ab8ccc287a0a327c817dc8a8ea3a5d3ca3cb55169777a1bfa30fe9f0df842eb3978dbd6737ba053683114bdaed7819b30ab8baec1fb9a2a96fee4dabc72f319cec9869da3b0b0a04d98297a896312d18da40240ed9a527f4c01c73edd3ea1f7c28338d1d863d97ca070451b5f2a402b497659eb18e648ac46f39c0068cc91436eb0b082b1d06dd63da066e866f800200512b0d3e534c547f4d2012429152cc9693bf1553cc22361627ba003fc4e648aafdadd7a9fa7cb534103f08dc699413ecda22bda46898bfb792429a0b46a167c66b50c74227d03a68971e124fdd011d6c90f5a08f6fe30ae34de603ca0a7ced66271235bc27b154f37bee6d9a1366cd253176c96de707d124fcc593c35a0f4f09b104a86cefc5c282d393b415e6c224eb8a463386448ebebfad9f9f53c9680f90211a05f93540f4317a4c6d8b73556a7ffdab6fcf0aa36af84b8c4bd2a3e7114e2da4ea05dd8c13b1b83485911f5e1185669f7d5559c260193a72e52597a3e80736c248ca03d50a67e8ec93696c35865d9f03814e95406c8d04e5decc320b9a24e5beee1baa0a928e2ea8773ba69dde5344d69069b237667dbaaa69e86133d4e444e432799b1a0ebb2cbf0c3314ddf681f21a29fa17b320094684ba35e725bc36bbc407821cfa3a0762aeb8161d2b1b8a5ee51d1ede36f51cc2dad7e0c4d0ff097b89c831aff8c35a0957a8eaaac924688482d21a95b7a7f01889ab39a7a50d58efaaffa9e486ae071a046c10b0c15aa83973ea4b108f50bad2638941550fce7c9308c8b968abee271f8a08a831384faa68f9caa047a6200464e11cfe5f9f700a5ed9435e5241d9d2a501ca020630d0f41d1f38c61fc8d3fc6170f6f11fc52ade454930a3b5e4f4491b47467a04539a99793f29484fdbd39b606f27265499acb3c24461f48858655f07166f0dfa05fd40548cfae17d12e103db98572f22cdc8dd3ec670be570727a7ff68f6bce9fa032efe866f058f79ef06de75f682e10773576eb9fca3f950fda96ea9926784685a05c170d685d29417781f678b746174c7500e7c228b4bd71bcfe9f5421742a0b67a0c3fb71b77522f06c4a4e4cb7029e7faeb747b8e446460586ea0d5e9abae68cd9a03f2294bf8bea287c7afafde4b39aaa56716230ef425ece688f6a78fcadf5f49e80f9013180a0c2cb770a3d18eb1214a782cc81b79a7fd772716c2d050ef66011095c3774e8f7a08fc7d7da06fba7ffa69b095aae41147e3a55b89644682057cedab705ba7aefd5a05975b434f69398107a4d1729f8f56e75247df09c65b1a750797818607bf118df80a026cea4c13260b2a1dd74bb6fcc7cc36162d2856ce691a36165c633ba68f7b783a0f7b0c667509a4ce937c487b45bc53c0700543daf4f8c127fbe475b4e1084d2328080a0454eca3fcc32afd4c4000ccbb47732bbce342b1a9d374fb5872162f2c873625fa0b3e6c44579a731cc730a5472e83c6098fa2943e5b2c72f4475f0afea76848a87a03b8c951788b8c93366aedbf88f6c1ca6085cd0249025ce542f19294b40bb92f180a0a10cfa51ae290afebd64a5b530db7088fa0b02f22ce9b0838135b422b885dee5808080e482000ea07b2632b8b97e159d88f112a8dd9d44df2f3c4502e0c79a29297ea7f61f41f311f851a030590b16841225b9590cdc95b19176201d442ca0b931c6e4314d20a1c772ea9ba052e8f9f247cd159c65b304863d444087f6a60d7dbec3a0e4fa09f007b5a1c64f808080808080808080808080808080f86c9c20120c458c4c09a9448628f84e81161b308d5c4041a3d3a1ea329d0eb84df84b0487400e8b4f1c9c00a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47022440bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e22442465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c8162244295e26495cef6f69dfa69911d9d8e4f3bbadb89b977cf58294f7239d515e15b24cfeb82494056cf691eaf729b165f32c9757c429dba5051155903067e56ebe3698678e9122442d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab022443f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a224461dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d25224469c77a677c40c7fbea129d4b171a39b7a8ddabfab2317f59d86abfaf690850223d90e9e7593d91a29331dfc2f84d5adecc75fc39ecab4632c1b4400a3dd1e1298835bcca224472b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a5122447ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e22448b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d788694852244a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b7412244b218c5d6af1f979ac42bc68d98a5a0d796c6ab01b659ad0fbd9f515893fdd740b29ba0772dbde9b4635921dd91bd2963a0fc855e31f6338f45b211c4e9dedb7f2eb09de72244b4dd66d7c2c7e57f628210187192fb89d4b99dd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002244be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cd2244cc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a4192244d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce7392244e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d212244e9ae3261a475a27bb1028f140bc2a7c843318afd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002244ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c1921832244ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5b2244ef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd0756e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd02a440bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e2a4412d810c13e42811e9907c02e02d1fad46cfa18bab679cbab0276ac30ff5f198e5e1dedf6b84959129f70fe7a07fcdf13444ba45b5dbaa7b1f650adf8b0acbecd04e2675b2a442465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c8162a442d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab02a443f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a2a4461dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d252a4470f657164e5b75689b64b7fd1fa275f334f28e1896a26afa1295da81418593bd12814463d9f6e45c36a0e47eb4cd3e5b6af29c41e2a3a5636430155a466e216585af3ba72a4472b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a512a447ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e2a448b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d788694852a44a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b7412a44b4dd66d7c2c7e57f628210187192fb89d4b99dd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a44be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cd2a44cc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a4192a44d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce7392a44d93dbfb27e027f5e9e6da52b9e1c413ce35adc11b313f9cba57c63a84edb4079140e6dbd7829e5023c9532fce57e9fe602400a2953f4bf7dab66cca16e97be95d4de70442a44e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d212a44e9ae3261a475a27bb1028f140bc2a7c843318afd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a44ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c1921832a44ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5b2a44ef0274e31810c9df02f98fafde0f841f4e66a1cd98cbf822e4bc29f1701ac0350a3d042cd0756e9f74822c6481773ceb000641c51b870a996fe0f6a844510b1061f38cd0").to_vec(); + let mut any = hex!("0a282f6962632e6c69676874636c69656e74732e7061726c69612e76312e4d69736265686176696f757212cf370a0b78782d7061726c69612d3112de1b0ab4060ab106f9032ea0268b5cdf7f6414cb54b00626c619892e5f3b693d568d546ff76198667f9e487ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0225560657909c76bbd1111cfa8a11f7ade19c80a315f013a920031ce76562e3ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002820d1b8402625a0080846699bfd7b90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b860b0b171c0b05dca088e0a163582339da1076da795a317c65f77441585d1446fda6692ce27df7b2b01ef2d419c2f8eb2f50b4e2f5856d9fb438f073c3e0aea72930333a6775d59096ce7560320504bb9bb4b17725edc5221491a3ac0bf64ec1f7ff848820d19a0e73c8182c6ff44e893b468600184209f9ffc5017be041533385658b98ee5675a820d1aa0268b5cdf7f6414cb54b00626c619892e5f3b693d568d546ff76198667f9e487b80649d4b1ea49d34532d24281cff713c1a1ffa9ad10ceaae118d02b19ec8a57bb4137e8ec449a3798de7cbec3a22d43d1377c84f045550e73e7100bb377df2753f01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800ab4060ab106f9032ea018b177b16b907b473a20b82a7c61d76f505a1f740c540e950f93c4210319a33ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a0225560657909c76bbd1111cfa8a11f7ade19c80a315f013a920031ce76562e3ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002820d1c8402625a0080846699bfdab90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b86083fcfb7f3c9d99995d330e6b953282f6c349af68cd4c523e1d635aa51ec49a2db651d824974ab9e7cf254e7e1b7e15cb0611ceb6adda365b8ee54d04c222b7f64dcacf94b4eb61671653396e1fe8840737444731d6c8d144d553a757e2327825f848820d1aa0268b5cdf7f6414cb54b00626c619892e5f3b693d568d546ff76198667f9e487b820d1ba018b177b16b907b473a20b82a7c61d76f505a1f740c540e950f93c4210319a33b80ddc0dfa730aa9a6de6089c20d1728803b04b4d7872a2b01c90e7cad663379a8a3f8676574fb5341ec662c890cae04fed92eaed9689c3b0c5421ea85fc3e42b5801a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800ab4060ab106f9032ea0220755141e26b1c68c8f887b41172aa93e3267f9f0ae7b49cfd1c7002558bcb4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0225560657909c76bbd1111cfa8a11f7ade19c80a315f013a920031ce76562e3ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002820d1d8402625a0080846699bfddb90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b860af867e0589e50a2571bfdec447fae755aade11b113b67c7928ef8bd3225a6aa29a0e29b7ab24d4952ebcbfd320258a41071e5875b547f4265c7eeb45ab4989294328db719d94157619bca873e451c3709447ecb0fa349df1084da580bb46a425f848820d1ba018b177b16b907b473a20b82a7c61d76f505a1f740c540e950f93c4210319a33b820d1ca0220755141e26b1c68c8f887b41172aa93e3267f9f0ae7b49cfd1c7002558bcb4804613f2a8116641990a7d1ce90f946e079891aa1d7904c01e078df492f1ef4dff120465d060478da7542c7cd65621d68d47c35e20482385ca5af9d58329eeac1e00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180801203109a1a1a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0eec2a9e5f0342238c9790975e393915d8ef68ade66edfeb220210a2b13a89464a0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a08851197273e914fa4bdd7b07c2fec3f243a63d2298ed39c2b0a78c4f7da9ddd880a0a74e307420bf9966d5db9a83ce48edc32c7a8e43328c6373de6875cefa04ad7aa0e502f113ade32bee3770b5a0117fa799c8812e5ab5a239e3878660c59c3537fda00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0d4182165b298d7b52b0f2064d19ab8bdad2b3955fa5b3d85c00673beb97e124480f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a03f47312ca98ac1f6ae9db9752c2a33529723b64e654d87f7847cee0382edfb55a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba82244a7876ea32e7a748c697d01345145485561305b24903201f874819815e1a3f183c4addc814b71ec0e573e07f79ee9082926d82dd1711d6c45a9cc8841916d8563c2f80baa2244d9a13701eafb76870cb220843b8c6476824bfa15a82968379b116362f75bdb7cc4be8ca0ceea7c0f2e74be7c8f289cda6dcbc5edbb26400e1306c2de06f52a9a583dab992a448fdaaa7e6631e438625ca25c857a3727ea28e56593428ee663799df81ea82bc8445a7d93c891ef324b5f4438eb766bcf75fc405fb79d3f618fcdd17f107b374368ef512f2a44a7876ea32e7a748c697d01345145485561305b24903201f874819815e1a3f183c4addc814b71ec0e573e07").to_vec(); + let any2 = hex!("f79ee9082926d82dd1711d6c45a9cc8841916d8563c2f80baa300138011ade1b0ab4060ab106f9032ea0268b5cdf7f6414cb54b00626c619892e5f3b693d568d546ff76198667f9e487ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002820d1b8402625a0080846699bfd7b90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b860b0b171c0b05dca088e0a163582339da1076da795a317c65f77441585d1446fda6692ce27df7b2b01ef2d419c2f8eb2f50b4e2f5856d9fb438f073c3e0aea72930333a6775d59096ce7560320504bb9bb4b17725edc5221491a3ac0bf64ec1f7ff848820d19a0e73c8182c6ff44e893b468600184209f9ffc5017be041533385658b98ee5675a820d1aa0268b5cdf7f6414cb54b00626c619892e5f3b693d568d546ff76198667f9e487b80649d4b1ea49d34532d24281cff713c1a1ffa9ad10ceaae118d02b19ec8a57bb4137e8ec449a3798de7cbec3a22d43d1377c84f045550e73e7100bb377df2753f01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800ab4060ab106f9032ea018b177b16b907b473a20b82a7c61d76f505a1f740c540e950f93c4210319a33ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a0225560657909c76bbd1111cfa8a11f7ade19c80a315f013a920031ce76562e3ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002820d1c8402625a0080846699bfdab90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b86083fcfb7f3c9d99995d330e6b953282f6c349af68cd4c523e1d635aa51ec49a2db651d824974ab9e7cf254e7e1b7e15cb0611ceb6adda365b8ee54d04c222b7f64dcacf94b4eb61671653396e1fe8840737444731d6c8d144d553a757e2327825f848820d1aa0268b5cdf7f6414cb54b00626c619892e5f3b693d568d546ff76198667f9e487b820d1ba018b177b16b907b473a20b82a7c61d76f505a1f740c540e950f93c4210319a33b80ddc0dfa730aa9a6de6089c20d1728803b04b4d7872a2b01c90e7cad663379a8a3f8676574fb5341ec662c890cae04fed92eaed9689c3b0c5421ea85fc3e42b5801a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800ab4060ab106f9032ea0220755141e26b1c68c8f887b41172aa93e3267f9f0ae7b49cfd1c7002558bcb4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0225560657909c76bbd1111cfa8a11f7ade19c80a315f013a920031ce76562e3ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002820d1d8402625a0080846699bfddb90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b860af867e0589e50a2571bfdec447fae755aade11b113b67c7928ef8bd3225a6aa29a0e29b7ab24d4952ebcbfd320258a41071e5875b547f4265c7eeb45ab4989294328db719d94157619bca873e451c3709447ecb0fa349df1084da580bb46a425f848820d1ba018b177b16b907b473a20b82a7c61d76f505a1f740c540e950f93c4210319a33b820d1ca0220755141e26b1c68c8f887b41172aa93e3267f9f0ae7b49cfd1c7002558bcb4804613f2a8116641990a7d1ce90f946e079891aa1d7904c01e078df492f1ef4dff120465d060478da7542c7cd65621d68d47c35e20482385ca5af9d58329eeac1e00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180801203109a1a1a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0eec2a9e5f0342238c9790975e393915d8ef68ade66edfeb220210a2b13a89464a0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a08851197273e914fa4bdd7b07c2fec3f243a63d2298ed39c2b0a78c4f7da9ddd880a0a74e307420bf9966d5db9a83ce48edc32c7a8e43328c6373de6875cefa04ad7aa0e502f113ade32bee3770b5a0117fa799c8812e5ab5a239e3878660c59c3537fda00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0d4182165b298d7b52b0f2064d19ab8bdad2b3955fa5b3d85c00673beb97e124480f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a03f47312ca98ac1f6ae9db9752c2a33529723b64e654d87f7847cee0382edfb55a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba82244a7876ea32e7a748c697d01345145485561305b24903201f874819815e1a3f183c4addc814b71ec0e573e07f79ee9082926d82dd1711d6c45a9cc8841916d8563c2f80baa2244d9a13701eafb76870cb220843b8c6476824bfa15a82968379b116362f75bdb7cc4be8ca0ceea7c0f2e74be7c8f289cda6dcbc5edbb26400e1306c2de06f52a9a583dab992a448fdaaa7e6631e438625ca25c857a3727ea28e56593428ee663799df81ea82bc8445a7d93c891ef324b5f4438eb766bcf75fc405fb79d3f618fcdd17f107b374368ef512f2a44a7876ea32e7a748c697d01345145485561305b24903201f874819815e1a3f183c4addc814b71ec0e573e07f79ee9082926d82dd1711d6c45a9cc8841916d8563c2f80baa30013801").to_vec(); any.extend(any2); let any: Any = any.try_into().unwrap(); // check if misbehavior @@ -1068,11 +1082,7 @@ mod test { let err = client .update_client(&ctx, client_id.clone(), any.clone()) .unwrap_err(); - assert!( - format!("{:?}", err).contains("UnexpectedHeaderRelation: 32160267 32160268"), - "{}", - err - ); + assert_err(err, "UnexpectedHeaderRelation: 3355 3356"); // fail: client state is frozen let ctx = MockClientReader { @@ -1085,11 +1095,7 @@ mod test { let err = client .update_client(&ctx, client_id.clone(), any.clone()) .unwrap_err(); - assert!( - format!("{:?}", err).contains("ClientFrozen: xx-parlia-1"), - "{}", - err - ); + assert_err(err, "ClientFrozen: xx-parlia-1"); // fail: consensus state not found let ctx = MockClientReader { @@ -1099,11 +1105,7 @@ mod test { let err = client .update_client(&ctx, client_id.clone(), any.clone()) .unwrap_err(); - assert!( - format!("{:?}", err).contains("consensus_state not found: client_id=xx-parlia-1"), - "{}", - err - ); + assert_err(err, "consensus_state not found: client_id=xx-parlia-1"); // fail: client state not found let ctx = MockClientReader { @@ -1111,10 +1113,10 @@ mod test { consensus_state: BTreeMap::new(), }; let err = client.update_client(&ctx, client_id, any).unwrap_err(); - assert!( - format!("{:?}", err).contains("client_state not found: client_id=xx-parlia-1"), - "{}", - err - ); + assert_err(err, "client_state not found"); + } + + fn assert_err(err: light_client::Error, contains: &str) { + assert!(format!("{:?}", err).contains(contains), "{}", err); } } diff --git a/light-client/src/client_state.rs b/light-client/src/client_state.rs index 096f010..ee00f71 100644 --- a/light-client/src/client_state.rs +++ b/light-client/src/client_state.rs @@ -77,7 +77,7 @@ impl ClientState { .try_into() .map_err(Error::UnexpectedStorageRoot)?, timestamp: header.timestamp()?, - current_validators_hash: header.current_epoch_validators_hash()?, + current_validators_hash: header.current_epoch_validators_hash(), previous_validators_hash: header.previous_epoch_validators_hash(), }; @@ -269,21 +269,27 @@ mod test { use crate::errors::Error; use light_client::types::{Any, Time}; use parlia_ibc_proto::ibc::core::client::v1::Height; + use rstest::rstest; use crate::consensus_state::ConsensusState; + use crate::fixture::*; + use crate::header::epoch::Epoch; use crate::header::eth_header::ETHHeader; - use crate::header::testdata::{ - header_31297200, header_31297201, header_31297202, mainnet, validators_in_31297000, - }; + use crate::header::eth_headers::ETHHeaders; + use crate::header::Header; - use crate::misc::{keccak_256_vec, new_timestamp, ChainId}; - use parlia_ibc_proto::ibc::lightclients::parlia::v1::ClientState as RawClientState; + use crate::misc::{new_timestamp, ChainId}; + use alloc::boxed::Box; use parlia_ibc_proto::ibc::lightclients::parlia::v1::Header as RawHeader; + use parlia_ibc_proto::ibc::lightclients::parlia::v1::{ + ClientState as RawClientState, EthHeader, + }; - #[test] - fn test_error_check_header_and_update_state() { + #[rstest] + #[case::localnet(localnet())] + fn test_error_check_header_and_update_state(#[case] hp: Box) { let cs = ClientState { - chain_id: mainnet(), + chain_id: hp.network(), ibc_store_address: [0u8; 20], ibc_commitments_slot: [0u8; 32], trusting_period: Duration::from_millis(1001), @@ -293,58 +299,58 @@ mod test { }; // fail: check_header - let h = &header_31297200(); + let h = &hp.epoch_header(); let cons_state = ConsensusState { state_root: [0u8; 32], timestamp: new_timestamp(h.timestamp).unwrap(), - current_validators_hash: keccak_256_vec(&validators_in_31297000()), - previous_validators_hash: keccak_256_vec(&validators_in_31297000()), + current_validators_hash: hp.previous_epoch_header().epoch.unwrap().hash(), + previous_validators_hash: hp.previous_epoch_header().epoch.unwrap().hash(), }; - let raw = RawHeader { - headers: vec![h.try_into().unwrap()], - trusted_height: Some(Height { + let header = Header::new( + vec![1], + ETHHeaders { + target: hp.epoch_header(), + all: vec![], + }, + Height { revision_number: 0, revision_height: h.number - 1, - }), - account_proof: vec![], - current_validators: if h.is_epoch() { - h.get_validator_set().unwrap().validators - } else { - vec![] }, - previous_validators: validators_in_31297000(), - }; + hp.previous_epoch_header().epoch.unwrap(), + hp.epoch_header().epoch.unwrap(), + ); let now = new_timestamp(h.timestamp + 1).unwrap(); - let invalid_header: Header = raw.clone().try_into().unwrap(); let err = cs - .check_header_and_update_state(now, &cons_state, invalid_header) + .check_header_and_update_state(now, &cons_state, header.clone()) .unwrap_err(); match err { Error::InvalidVerifyingHeaderLength(number, size) => { assert_eq!(number, h.number); - assert_eq!(size, raw.headers.len()); + assert_eq!(size, header.eth_header().all.len()); } err => unreachable!("{:?}", err), } // fail: resolve_account - let raw = RawHeader { - headers: vec![ - (&header_31297200()).try_into().unwrap(), - (&header_31297201()).try_into().unwrap(), - (&header_31297202()).try_into().unwrap(), - ], - trusted_height: Some(Height { + let header = Header::new( + vec![1], + ETHHeaders { + target: hp.epoch_header(), + all: vec![ + hp.epoch_header(), + hp.epoch_header_plus_1(), + hp.epoch_header_plus_2(), + ], + }, + Height { revision_number: 0, revision_height: h.number - 1, - }), - account_proof: vec![1], - current_validators: header_31297200().get_validator_bytes().unwrap(), - previous_validators: validators_in_31297000(), - }; - let valid_header: Header = raw.try_into().unwrap(); + }, + hp.previous_epoch_header().epoch.unwrap(), + hp.epoch_header().epoch.unwrap(), + ); let err = cs - .check_header_and_update_state(now, &cons_state, valid_header) + .check_header_and_update_state(now, &cons_state, header) .unwrap_err(); match err { Error::InvalidProofFormatError(value) => { @@ -354,23 +360,26 @@ mod test { } } - #[test] - fn test_error_check_header() { - let header_fn = |revision: u64, h: alloc::vec::Vec| { + #[rstest] + #[case::localnet(localnet())] + fn test_error_check_header(#[case] hp: Box) { + let header_fn = |revision: u64, h: ÐHeader, h_rlp: alloc::vec::Vec| { let trusted_height = Height { revision_number: revision, - revision_height: h[0].number - 1, + revision_height: h.number - 1, }; let raw = RawHeader { - headers: h.iter().map(|e| e.try_into().unwrap()).collect(), + headers: vec![EthHeader { header: h_rlp }], trusted_height: Some(trusted_height), account_proof: vec![], - current_validators: if h[0].is_epoch() { - h[0].get_validator_set().unwrap().validators + current_validators: if h.is_epoch() { + h.epoch.clone().unwrap().validators().clone() } else { - vec![h[0].coinbase.clone()] + vec![h.coinbase.clone()] }, - previous_validators: vec![h[0].coinbase.clone()], + previous_validators: vec![h.coinbase.clone()], + previous_turn_length: 1, + current_turn_length: 1, }; raw.try_into().unwrap() }; @@ -387,15 +396,15 @@ mod test { let mut cons_state = ConsensusState { state_root: [0u8; 32], timestamp: new_timestamp(0).unwrap(), - current_validators_hash: [0u8; 32], - previous_validators_hash: [0u8; 32], + current_validators_hash: Epoch::new(vec![[0u8; 20].to_vec()].into(), 1).hash(), + previous_validators_hash: Epoch::new(vec![[0u8; 20].to_vec()].into(), 1).hash(), }; // fail: validate_trusting_period - let h = header_31297200(); + let h = hp.epoch_header(); let now = new_timestamp(h.timestamp - 1).unwrap(); cons_state.timestamp = new_timestamp(h.timestamp).unwrap(); - let header = header_fn(0, vec![h]); + let header = header_fn(0, &h, hp.epoch_header_rlp()); let err = cs.check_header(now, &cons_state, &header).unwrap_err(); match err { Error::HeaderFromFuture(_, _, _) => {} @@ -403,10 +412,10 @@ mod test { } // fail: revision check - let h = header_31297200(); + let h = hp.epoch_header(); let now = new_timestamp(h.timestamp + 1).unwrap(); cons_state.timestamp = new_timestamp(h.timestamp).unwrap(); - let header = header_fn(1, vec![h]); + let header = header_fn(1, &h, hp.epoch_header_rlp()); let err = cs.check_header(now, &cons_state, &header).unwrap_err(); match err { Error::UnexpectedHeaderRevision(n1, n2) => { @@ -417,11 +426,11 @@ mod test { } // fail: verify_validator_set - let h = header_31297200(); - let header = header_fn(0, vec![h.clone()]); + let h = hp.epoch_header(); + let header = header_fn(0, &h, hp.epoch_header_rlp()); let err = cs.check_header(now, &cons_state, &header).unwrap_err(); match err { - Error::UnexpectedPreviousValidatorsHash(h1, h2, _, _) => { + Error::UnexpectedUntrustedValidatorsHashInEpoch(h1, h2, _, _) => { assert_eq!(h1.revision_height(), h.number - 1); assert_eq!(h2.revision_height(), h.number); } @@ -429,9 +438,9 @@ mod test { } // fail: header.verify - let h = header_31297200(); - cons_state.current_validators_hash = keccak_256_vec(&[h.coinbase.clone()]); - let header = header_fn(0, vec![h.clone()]); + let h = hp.epoch_header(); + cons_state.current_validators_hash = Epoch::new(vec![h.coinbase.clone()].into(), 1).hash(); + let header = header_fn(0, &h, hp.epoch_header_rlp()); let err = cs.check_header(now, &cons_state, &header).unwrap_err(); match err { Error::UnexpectedCoinbase(number) => { diff --git a/light-client/src/errors.rs b/light-client/src/errors.rs index 51ffd19..f92d14b 100644 --- a/light-client/src/errors.rs +++ b/light-client/src/errors.rs @@ -78,6 +78,8 @@ pub enum Error { ProofRLPError(rlp::DecoderError), InvalidProofFormatError(Vec), MissingValidatorInEpochBlock(BlockNumber), + MissingTurnLengthInEpochBlock(BlockNumber), + MissingEpochInfoInEpochBlock(BlockNumber), MissingNextValidatorSet(BlockNumber), MissingCurrentValidatorSet(BlockNumber), UnexpectedPreviousValidatorsHash(Height, Height, Hash, Hash), @@ -89,6 +91,10 @@ pub enum Error { UnexpectedNextCheckpointHeader(BlockNumber, BlockNumber), UnexpectedNextNextCheckpointHeader(BlockNumber, BlockNumber), MissingTrustedCurrentValidators(BlockNumber), + UnexpectedDifficultyInTurn(BlockNumber, u64, usize), + UnexpectedDifficultyNoTurn(BlockNumber, u64, usize), + UnexpectedUntrustedValidatorsHashInEpoch(Height, Height, Hash, Hash), + UnexpectedCurrentValidatorsHashInEpoch(Height, Height, Hash, Hash), // Vote attestation UnexpectedTooManyHeadersToFinalize(BlockNumber, usize), @@ -104,6 +110,8 @@ pub enum Error { InsufficientValidatorCount(BlockNumber, usize, usize), UnexpectedVoteAddressCount(BlockNumber, usize, usize), UnexpectedBLSSignatureLength(usize), + UnexpectedTurnLength(u8), + UnexpectedExtraDataLength(usize), // Misbehaviour MissingHeader1, @@ -258,6 +266,12 @@ impl core::fmt::Display for Error { Error::MissingValidatorInEpochBlock(e1) => { write!(f, "MissingValidatorInEpochBlock : {:?}", e1) } + Error::MissingEpochInfoInEpochBlock(e1) => { + write!(f, "MissingEpochInfoInEpochBlock : {:?}", e1) + } + Error::MissingTurnLengthInEpochBlock(e1) => { + write!(f, "MissingTurnLengthInEpochBlock : {:?}", e1) + } Error::MissingPreviousValidators(e1) => { write!(f, "MissingPreviousValidators : {:?}", e1) } @@ -334,6 +348,32 @@ impl core::fmt::Display for Error { Error::LCPError(e1) => { write!(f, "LCPError: {}", e1) } + Error::UnexpectedDifficultyInTurn(e1, e2, e3) => { + write!(f, "UnexpectedDifficultyInTurn : {} {} {}", e1, e2, e3) + } + Error::UnexpectedDifficultyNoTurn(e1, e2, e3) => { + write!(f, "UnexpectedDifficultyNoTurn : {} {} {}", e1, e2, e3) + } + Error::UnexpectedTurnLength(e1) => { + write!(f, "UnexpectedTurnLength : {}", e1) + } + Error::UnexpectedExtraDataLength(e1) => { + write!(f, "UnexpectedExtraDataLength: {}", e1) + } + Error::UnexpectedUntrustedValidatorsHashInEpoch(e1, e2, e3, e4) => { + write!( + f, + "UnexpectedUntrustedValidatorsHashInEpoch : {:?} {:?} {:?} {:?}", + e1, e2, e3, e4 + ) + } + Error::UnexpectedCurrentValidatorsHashInEpoch(e1, e2, e3, e4) => { + write!( + f, + "UnexpectedCurrentValidatorsHashInEpoch : {:?} {:?} {:?} {:?}", + e1, e2, e3, e4 + ) + } } } } diff --git a/light-client/src/fixture/localnet.rs b/light-client/src/fixture/localnet.rs new file mode 100644 index 0000000..9ba1664 --- /dev/null +++ b/light-client/src/fixture/localnet.rs @@ -0,0 +1,150 @@ +use hex_literal::hex; + +use std::prelude::rust_2015::Vec; + +use crate::header::eth_header::ETHHeader; +use crate::header::eth_headers::ETHHeaders; + +use crate::fixture::{decode_header, Network, UpdateClientEpochInput, UpdateClientNonEpochInput}; +use crate::misc::{Address, ChainId}; + +pub struct Localnet; + +impl Network for Localnet { + fn network(&self) -> ChainId { + ChainId::new(9999) + } + + fn ibc_store_address(&self) -> Address { + hex!("2F5703804E29F4252FA9405B8D357220d11b3bd9") + } + + fn previous_epoch_header(&self) -> ETHHeader { + // height 200 + decode_header(hex!("f90391a0844dee9abff97d261ae0049fe38246ac10aba49f2b8618f28f7c2d19e62eccf9a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a0ecf1aa30fa754576ac4abc3cf2a61d1babd41c7e5515855efd857b2d3f37866ba00f0ea7d212c4aaca329b03f5e9ed9c69d3641eb5e03a4edb69b61e6f9d8d51efa0c3372a1f332fc4245e1a9fdcb62580fc6dae741087a8029560f19216dd3d58b9b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000281c88402625a00826c7484669a6a91b90173d98301040b846765746889676f312e32312e3132856c696e7578000020155b72048fdaaa7e6631e438625ca25c857a3727ea28e565b94a73be71b4a5703b4d0b36e4f65d52615b668b385efc047f7f385ace378981fa3750a0bc16ca6f8217be599bcfa274b2e42bc54d19116d2348ac83461e2e0915d508ad921ebe99c27c8fdbd30aecdbe86f95aee2e06995f83ebeb327924669629f193ffd3257315c79ed5a4867ec53b502b5e6d9a13701eafb76870cb220843b8c6476824bfa158c66a3f3d2fba1d440da8edc79b59ed9a3a43db62bd7659f7d4e25073f9241dba560600b23e26c30d48ea0395eeeb4ede04db2de85453e0936b441c339a26d10cfa71b50a50dd5edefbafd33740101d074b6d58b56a787a7644ddfff77d0c00f9e62cc58c931e671afc564f3f6e255cc6fc8a567015cbc63c3d778cef5e8dbfdaf1fd8f758a764f2667aad2d3775954e4ac23e726226b66f0a94631bd0b6d937b22955d73eed65a31a6f535662f51cc7547143f6f201a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080").to_vec()) + } + + fn epoch_header_rlp(&self) -> Vec { + // height 400 + hex!("f90442a04ec3c90370deeeab62de72108470bccac75d1abe118a778f01afa7a99c976a5da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a08d30abd786d85a8a10ba441afafdf853b7fd2769351f6600402b88a1ac2d4d7aa0015ebe4a5d6cd56f0bf97db1d21746f59ab5cbecf216e34753920d815403ada2a03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028201908402625a008229a884669a6ce9b90223d98301040b846765746889676f312e32312e3132856c696e7578000020155b72048fdaaa7e6631e438625ca25c857a3727ea28e565b94a73be71b4a5703b4d0b36e4f65d52615b668b385efc047f7f385ace378981fa3750a0bc16ca6f8217be599bcfa274a7876ea32e7a748c697d01345145485561305b248cd0ede772633b8baea9958f9b602db36d78934d948244a13c2d66e998f987783276e9aee6facbff50b0d63574406b51b2e42bc54d19116d2348ac83461e2e0915d508ad921ebe99c27c8fdbd30aecdbe86f95aee2e06995f83ebeb327924669629f193ffd3257315c79ed5a4867ec53b502b5e6e04db2de85453e0936b441c339a26d10cfa71b50a50dd5edefbafd33740101d074b6d58b56a787a7644ddfff77d0c00f9e62cc58c931e671afc564f3f6e255cc6fc8a56701f8ae0fb8608b6dc552b410a6fa44fa31643850bcb314f1d4edb32c0c79ee3efef5397691f3685d80057d77510a00e77a39e8b2497419053c3b81a8901e85590a20a0a2dad529c82f6c175ec3ebca8a9112415aa94718af673c16c0e90e327e27709666e499f84882018ea0709f88597f05218c198818991cf5598c9280db30d5bfe899da9b7a8c963bff6c82018fa04ec3c90370deeeab62de72108470bccac75d1abe118a778f01afa7a99c976a5d8012518315e9c22a4a648f4d26efcf57f877a26498de6d53fe7a267e8d5ef01482009817fc9de90ca8008ef1f420aa606ddc0c56a975bace3906601fd5cde657d600a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080").to_vec() + } + + fn epoch_header_plus_1_rlp(&self) -> Vec { + hex!("f9032ea0e256fac4dd62cc71eaefd8d6c24ae5209c0e48f5c0b62bcced06dfa838c2ad31a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada08d30abd786d85a8a10ba441afafdf853b7fd2769351f6600402b88a1ac2d4d7aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028201918402625a008084669a6cecb90111d98301040b846765746889676f312e32312e3132856c696e7578000020155b72f8ae0fb8609338bf42b6ef715e9c887e1b285e706355c2a993cd227497b447f8aad4b7fa44d18cd895862e1a2b961b78656d620f9c015e777cf9bcb6c50e1db2783818bd91f647f6879f8bd199f266f1166f9241f00f955fb5210e7e89e7678680900d1cc1f84882018fa04ec3c90370deeeab62de72108470bccac75d1abe118a778f01afa7a99c976a5d820190a0e256fac4dd62cc71eaefd8d6c24ae5209c0e48f5c0b62bcced06dfa838c2ad3180d6c559fceda3795918a2fdd34cb4f77608c8095b67091aadcef5d5c4efe09fc0477a1977c0037f19244240648637c3c5ec9fe22f1db4899a022575bec96cfccf01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080").to_vec() + } + + fn epoch_header_plus_2(&self) -> ETHHeader { + decode_header(hex!("f9032ea0669cf9fc3b3d480d7a8de1cc051e1d95fa24be8870aa93bb5bfc03f1d592db46a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a08d30abd786d85a8a10ba441afafdf853b7fd2769351f6600402b88a1ac2d4d7aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028201928402625a008084669a6cefb90111d98301040b846765746889676f312e32312e3132856c696e7578000020155b72f8ae0fb8608d465cf004274c6caaddd041116c93f12cba458536d23efc6148134af357a685c7b84b1d3de59eb61b2756e7b99a99de00a6158245e16d23dd10602ef719836ce41862c567745727a145df4bde737415e8ffbec5056d4653b02fe1ddc8f21069f848820190a0e256fac4dd62cc71eaefd8d6c24ae5209c0e48f5c0b62bcced06dfa838c2ad31820191a0669cf9fc3b3d480d7a8de1cc051e1d95fa24be8870aa93bb5bfc03f1d592db468083bec325b33996ad2fc35e146d7e8fd215177b1423378d3b07cb73293d5384733488a981b64ae03cbcf44af281cfbd57431addbd8432042c49fb4c78d5573f0d01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080").to_vec()) + } + + fn epoch_header_plus_3(&self) -> ETHHeader { + decode_header(hex!("f9032ea0705444384ac2acf605c4ca8353e5070f37cc0976597dfdfc74413e278725eee7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a08d30abd786d85a8a10ba441afafdf853b7fd2769351f6600402b88a1ac2d4d7aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028201938402625a008084669a6cf2b90111d98301040b846765746889676f312e32312e3132856c696e7578000020155b72f8ae0fb860a6e88879bc7f8ff4ee90ba0776b414b97ffcb0a2bc4f9484075ea121e00b7ce27e21c0fbf76f34746b232e76a37cfc220011efbd7863237e75eb2830748736e9092847a283401bf6793e94d00619764884d012609cf5bace403e93b66f60c3bcf848820191a0669cf9fc3b3d480d7a8de1cc051e1d95fa24be8870aa93bb5bfc03f1d592db46820192a0705444384ac2acf605c4ca8353e5070f37cc0976597dfdfc74413e278725eee780f5171f7fc98ba3118543b55677128c397b07085a29dcd71c989c7f0eb602308342cf64470f85ebe31ebdda4244e7992b82ff2026ac461d0f2997332ccb99255201a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080").to_vec()) + } + + fn headers_before_checkpoint(&self) -> ETHHeaders { + vec![ + self.epoch_header(), + self.epoch_header_plus_1(), + self.epoch_header_plus_2(), + ] + .into() + } + + fn headers_across_checkpoint(&self) -> ETHHeaders { + let h404 = decode_header(hex!("f9032ea096cb50332bbf713e73255ff60f9bd09d8fd1c6aaa77e238877391578648ef27ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a08d30abd786d85a8a10ba441afafdf853b7fd2769351f6600402b88a1ac2d4d7aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028201948402625a008084669a6cf5b90111d98301040b846765746889676f312e32312e3132856c696e7578000020155b72f8ae0fb8609172e0bc45c783421222512ab2f9dd881f7416db9f0577699ee5fdd35c43655df184674ff0567f9a3e014778305f93c902b1d5c7389c8ef5733fcf458d6fa8fb7db16b0355fa5fa20d707d7e6d481ed52d59dc4da52a483100742e3b5a720b21f848820192a0705444384ac2acf605c4ca8353e5070f37cc0976597dfdfc74413e278725eee7820193a096cb50332bbf713e73255ff60f9bd09d8fd1c6aaa77e238877391578648ef27e8007b6d31837799df1d74bc66a1b12b5e4c485adac4b869b2b87160800c65418e3061d0ccf55b52c0ab7a50832c51f8d5d74aa2de7c481b9f87e83d9a73334009301a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080").to_vec()); + vec![self.epoch_header_plus_2(), self.epoch_header_plus_3(), h404].into() + } + + fn headers_after_checkpoint(&self) -> ETHHeaders { + let h404 = decode_header(hex!("f9032ea096cb50332bbf713e73255ff60f9bd09d8fd1c6aaa77e238877391578648ef27ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a08d30abd786d85a8a10ba441afafdf853b7fd2769351f6600402b88a1ac2d4d7aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028201948402625a008084669a6cf5b90111d98301040b846765746889676f312e32312e3132856c696e7578000020155b72f8ae0fb8609172e0bc45c783421222512ab2f9dd881f7416db9f0577699ee5fdd35c43655df184674ff0567f9a3e014778305f93c902b1d5c7389c8ef5733fcf458d6fa8fb7db16b0355fa5fa20d707d7e6d481ed52d59dc4da52a483100742e3b5a720b21f848820192a0705444384ac2acf605c4ca8353e5070f37cc0976597dfdfc74413e278725eee7820193a096cb50332bbf713e73255ff60f9bd09d8fd1c6aaa77e238877391578648ef27e8007b6d31837799df1d74bc66a1b12b5e4c485adac4b869b2b87160800c65418e3061d0ccf55b52c0ab7a50832c51f8d5d74aa2de7c481b9f87e83d9a73334009301a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080").to_vec()); + let h405 = decode_header(hex!("f9032ea03a48eae03d25e5b740a93befd16e8e4f9926727075d0a986c3448e69aa8acc62a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a08d30abd786d85a8a10ba441afafdf853b7fd2769351f6600402b88a1ac2d4d7aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028201958402625a008084669a6cf8b90111d98301040b846765746889676f312e32312e3132856c696e7578000020155b72f8ae0fb860aa33cabb6ecd6b5fd88cd0cf67fb9b7e9a87cd46699f6dc1c065a309494bcba543371190cd53d3f614f78e08bebd98360f8463999bc2a14ff20c1a771755745340e5728a58f48ff14530ab2616f5e020022ef47393fd041024c258faed646498f848820193a096cb50332bbf713e73255ff60f9bd09d8fd1c6aaa77e238877391578648ef27e820194a03a48eae03d25e5b740a93befd16e8e4f9926727075d0a986c3448e69aa8acc6280f8561d89c6a41e9eb05325d0c1087dc6f13efd20c591a4c4fa774a27156c2a30388b570eeac528d7521832243a8164043366dd1e94e030d966473462d7c5605a01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080").to_vec()); + vec![self.epoch_header_plus_3(), h404, h405].into() + } + + fn success_update_client_non_epoch_input(&self) -> UpdateClientNonEpochInput { + UpdateClientNonEpochInput { + header: hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212de1b0ab4060ab106f9032ea04788023231ff806fc9c20db23fce4c06c3b70d9038168334ec3e2095840ce534a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a044a1ff3b091f2f544a4d42c0772da7a8c26265f177d0472730efa0719c157d35a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028201f68402625a00808466992e3bb90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b860a5847b013e471a925b8122c9c748725825aef5d215d1ccee2b83af041eba4cf9ee211aed07fdeac7b4c2f7b85070208505e6849508cb950b2678fd27d40fb8e8a8656c050dd44f6ec33c226f108d15c6cab19080cfffbea81cdc7b1a09bc0463f8488201f4a0b4dfd14d8766b8fa4e64335fbcb53e56699c8948cb032d0bb628fc166a9321318201f5a04788023231ff806fc9c20db23fce4c06c3b70d9038168334ec3e2095840ce53480462103279b25cbd0540468881b0b90266b9ade0a60d6a93bba8a7ae4aff1d15477df78046011f78aeebf21fe63204b5e2b9b1aa8c7e26234482902addbb62a4001a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800ab4060ab106f9032ea0b1270c4b2a24c6bce1d07ec610c294d4b729b0c9c02d585e33018420bd6d8f5aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a044a1ff3b091f2f544a4d42c0772da7a8c26265f177d0472730efa0719c157d35a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028201f78402625a00808466992e3eb90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b86099624ac24cb33ea9d08bbc36916d4850fabbeea8f97d320a0493c574e4ec19f443070972f6c1737e0ca5269bdb11f16507096f009f7c1298d1ea37e22d2c0565cd5ae718284f80f5704228d6bc4d36ea63d7cd9a6077b15bf8e0c973c0b54f98f8488201f5a04788023231ff806fc9c20db23fce4c06c3b70d9038168334ec3e2095840ce5348201f6a0b1270c4b2a24c6bce1d07ec610c294d4b729b0c9c02d585e33018420bd6d8f5a80f3a3f4f618fa7a483fcc7f00b52e43e90085d5371c62a34f9a7150ad13921d805762782747f63307bee2a73980fc19c19af853800c7805fec26a3e405ea2b77500a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800ab4060ab106f9032ea0be1699ee1c35954f180299bc9579d59ff6d57e5205cdc35c570d83d9e647d6d1a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a044a1ff3b091f2f544a4d42c0772da7a8c26265f177d0472730efa0719c157d35a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028201f88402625a00808466992e41b90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b860af4473d99c25cbf6cce8b3b305ec3dbccff96d7c6007f123dbbcbda8286428a69da7f9145ced0f2275b11daf1b7ad1e514938274bc4f960d25026f23c2f2f8a5d8cd3d32d87b4c66062988a657dbb5cd625bb256f328e8a4a81d92f0a2389fd1f8488201f6a0b1270c4b2a24c6bce1d07ec610c294d4b729b0c9c02d585e33018420bd6d8f5a8201f7a0be1699ee1c35954f180299bc9579d59ff6d57e5205cdc35c570d83d9e647d6d18083abf2596f14299f17a96f652981b52bb794315aee435f3e277a031b4955f4866c5179198606ef2c2f691d3352d1d6daaf2a995e75212fb413f520604e7e412001a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080120310f5031a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea02da84052a06a138dc625b9f6b0020fa250e7b1862a9ff3db6516a7e32ff33698a0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a0c4514d3d96fbd80ddd21b28182a517e555c417cd7683f805860098cd28a49a4380a0a74e307420bf9966d5db9a83ce48edc32c7a8e43328c6373de6875cefa04ad7aa056f4d573349c475d8d0dd015ee77c80ccc34d5742c2a7f2c266480b61f24a050a00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0d4182165b298d7b52b0f2064d19ab8bdad2b3955fa5b3d85c00673beb97e124480f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a03f47312ca98ac1f6ae9db9752c2a33529723b64e654d87f7847cee0382edfb55a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e56593428ee663799df81ea82bc8445a7d93c891ef324b5f4438eb766bcf75fc405fb79d3f618fcdd17f107b374368ef512f2244d9a13701eafb76870cb220843b8c6476824bfa15a82968379b116362f75bdb7cc4be8ca0ceea7c0f2e74be7c8f289cda6dcbc5edbb26400e1306c2de06f52a9a583dab992a44a7876ea32e7a748c697d01345145485561305b24903201f874819815e1a3f183c4addc814b71ec0e573e07f79ee9082926d82dd1711d6c45a9cc8841916d8563c2f80baa2a44d9a13701eafb76870cb220843b8c6476824bfa15a82968379b116362f75bdb7cc4be8ca0ceea7c0f2e74be7c8f289cda6dcbc5edbb26400e1306c2de06f52a9a583dab9930013801").to_vec(), + trusted_height: 501, + trusted_current_validators_hash: hex!("92f25eb8500cae7c8548a61c6a03f4fc99690589b472b55e4c8ce25d0ce0f4d5"), + trusted_previous_validators_hash: hex!("5b514a7e8083146842c425a71aec83368ef4628442999a6d340d623ffb360c67"), + expected_storage_root: hex!("e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9") + } + } + + fn success_update_client_epoch_input(&self) -> UpdateClientEpochInput { + UpdateClientEpochInput { + header: hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ea1c0ac0070abd07f903baa0163d00e3a755c1dfba94d3a87b82ae4fbd31ac3400233606ab0c6084552ea907a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a0b0bb21f48df0039e57c69d0157fe2346579dcfd4686d4c460f1e6b0a21a9c65aa028255bd26759d78c76dfc514a6c56ba3ca09b796f8b4ed29746cd5d1708e6392a03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208988402625a008229a8846699a2e2b9019bd98301040b846765746889676f312e32312e3132856c696e75780000ffcc693e028fdaaa7e6631e438625ca25c857a3727ea28e56593428ee663799df81ea82bc8445a7d93c891ef324b5f4438eb766bcf75fc405fb79d3f618fcdd17f107b374368ef512fd9a13701eafb76870cb220843b8c6476824bfa15a82968379b116362f75bdb7cc4be8ca0ceea7c0f2e74be7c8f289cda6dcbc5edbb26400e1306c2de06f52a9a583dab9901f8ae03b8608c09a24f288f99a33d8f460676c20755d1ae4882aae146f8a7b70686f9da8fa483f9936492cec930d2e12e9dbde55d2b159e8489494b25033af825a7e9de9098e113314cbfb7e9116894e7acbe2d9997725c1dadfa1c87797f31adfe029e1268f848820896a0e94953cae18522809f395677c9d50f385c164df2bd08c6785ef73caabaab1ea6820897a0163d00e3a755c1dfba94d3a87b82ae4fbd31ac3400233606ab0c6084552ea907807a36b8b2b13a4f21512e1a4f47e9886adf4ede9107c86e34fe91c7001d5a60743af22d47507720ff67c07936b318094bbb033acc97c25c2fd996823556b3702401a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800ab4060ab106f9032ea0159bd78c921d172005fa4812b7bd17818128531fcc94d79d4c5dc2eac89e8d24a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0b0bb21f48df0039e57c69d0157fe2346579dcfd4686d4c460f1e6b0a21a9c65aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208998402625a0080846699a2e5b90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b8608a925326ca08415ac1c64130b3686da771563220c5f8e9086ba2d7f3988e3e1a99e5e92d741c4ae6ed8d670fdd0dd2f91852b62894209617212d0adc83c678281b07ad1a61bc219daae50352b47a040e4b863295eec93a0ffe1039f9430fd552f848820897a0163d00e3a755c1dfba94d3a87b82ae4fbd31ac3400233606ab0c6084552ea907820898a0159bd78c921d172005fa4812b7bd17818128531fcc94d79d4c5dc2eac89e8d24808d29c8af8a9703ddae74256526b88cc9e23453db7b802efbb5e13879a0a9ba1a39431d64b66992d3d95bddfdb5d810038e423e2b63a513dd1d56d860d06af67f01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180800ab4060ab106f9032ea019f886a89182b225d6d5f9fde2585225c7345a0dfec2d696d2883b2d457efff9a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a0b0bb21f48df0039e57c69d0157fe2346579dcfd4686d4c460f1e6b0a21a9c65aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000282089a8402625a0080846699a2e8b90111d98301040b846765746889676f312e32312e3132856c696e75780000ffcc693ef8ae03b860823f591b2f21bfbbc4ffed752a4763e48f998303580842aba1dbefc47e5559cc9888c41b4821a5f1708671de14c9025c031ec1bc30f62f07ab90fc8579556af7827de63e06d63945b1f134f8b7a1f59e7ece7fb08a902d137a19f0aa31757e71f848820898a0159bd78c921d172005fa4812b7bd17818128531fcc94d79d4c5dc2eac89e8d24820899a019f886a89182b225d6d5f9fde2585225c7345a0dfec2d696d2883b2d457efff9802dc6bbe4016c470f6013d0862e7f72c88166d10968d27eb42dc0857718c3393a3b925acd3352a6581b027a59999b83aad3008317c6f6b0b6fc0e448a4b0b5cbb00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421808012031097111a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0e7dfe8f84f2275550989049850d05064cc8b01fb231136d5a5d4c93d3a35e207a0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a05bd37b72fde8c8da4861cd3d3af70e498c5d49dd4d929f608ab3a34693fb394580a0a74e307420bf9966d5db9a83ce48edc32c7a8e43328c6373de6875cefa04ad7aa0a1be3efcd793a73f9c65da939fd72689098a7407794678fc846a0724d1bcd76ca00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0d4182165b298d7b52b0f2064d19ab8bdad2b3955fa5b3d85c00673beb97e124480f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a03f47312ca98ac1f6ae9db9752c2a33529723b64e654d87f7847cee0382edfb55a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e56593428ee663799df81ea82bc8445a7d93c891ef324b5f4438eb766bcf75fc405fb79d3f618fcdd17f107b374368ef512f2244d9a13701eafb76870cb220843b8c6476824bfa15a82968379b116362f75bdb7cc4be8ca0ceea7c0f2e74be7c8f289cda6dcbc5edbb26400e1306c2de06f52a9a583dab992a44a7876ea32e7a748c697d01345145485561305b24903201f874819815e1a3f183c4addc814b71ec0e573e07f79ee9082926d82dd1711d6c45a9cc8841916d8563c2f80baa2a44d9a13701eafb76870cb220843b8c6476824bfa15a82968379b116362f75bdb7cc4be8ca0ceea7c0f2e74be7c8f289cda6dcbc5edbb26400e1306c2de06f52a9a583dab9930013801").to_vec(), + trusted_height: 2199, + trusted_current_validators_hash: hex!("5b514a7e8083146842c425a71aec83368ef4628442999a6d340d623ffb360c67"), + trusted_previous_validators_hash: hex!("399334b2051da932262b42f25e5e59724c08df5c88d13c9d6bf5c51c33233aab"), + new_current_validators_hash: hex!("92f25eb8500cae7c8548a61c6a03f4fc99690589b472b55e4c8ce25d0ce0f4d5"), + new_previous_validators_hash: hex!("5b514a7e8083146842c425a71aec83368ef4628442999a6d340d623ffb360c67"), + expected_storage_root: hex!("e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9") + } + } + fn error_update_client_non_neighboring_epoch_input(&self) -> Vec { + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ae9080ae608f90463a0947b3bea434254e61a3cb8db3730b1f72f41387c5cafa6b70e442fb395febf1ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a0eb1d5bc6a9a390ac95eb3615129897e262958bf00049496ac246dbffa21cbcf4a0635e768d28c61dab2839060edf8f2eeb96b39f7d83c210292a6d535f8792ef9da03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028206408402625a008229a88466a222f7b90223d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2f04a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b6b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be3d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b3e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc109f8ae0fb860b0c4bfc658efc671dde996a36671539bac5b825b9cbe12605170bea0962f2076ac1fa677363bdf6b402d2bacb97b6cda0c8d4cbf078bcae5f3fa944a3a2c201e646c312dabb42fb511a0cc7f7ccd65ec8acd463451ad7d2966087bac9e49a075f84882063ea0d6eb0fd288eb7e595da1a30d123e291811d08a56481fbe9adea04f213e3ef2a482063fa0947b3bea434254e61a3cb8db3730b1f72f41387c5cafa6b70e442fb395febf1c808f56a07ca2497220c99fe729399e4affdc82b979356fc32312090ae8bab6c1fa7125fcaceeaed814d8b3fba2c7e870ddac117994c046246a19c59bcfbf1ef65901a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0a2d72a8ec56486c9a6f050753741172c6d48a0a9a0ceee3e4bd3bc8211c42919a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a0eb1d5bc6a9a390ac95eb3615129897e262958bf00049496ac246dbffa21cbcf4a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028206418402625a00808466a222fab90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb8608efb50f56bef7c6c09e58a679088e25ffc317b2e7adcb8c2395626a2d00d1f0cf14864344d22d5b33ca0610631f834be179f775ec3247a72f1755f4e4f4974dfc6a1f404d6600a7f83186cb1bec99c66b4752e1c34b692ed3eeb3bb745ddf790f84882063fa0947b3bea434254e61a3cb8db3730b1f72f41387c5cafa6b70e442fb395febf1c820640a0a2d72a8ec56486c9a6f050753741172c6d48a0a9a0ceee3e4bd3bc8211c42919809a1200e4dace2a075f92d8467b3f71b68e5293f0f66fa123e349f1484d77bf727211932b96e56cace0fc0e5951b23419ef84d631e19ddde29a1feeb55a09a36300a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0cc5f461c78150e7d776c24dfa8254ecd200e32d4125135bf2470eebce1ca142ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada0eb1d5bc6a9a390ac95eb3615129897e262958bf00049496ac246dbffa21cbcf4a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028206428402625a00808466a222fdb90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860afca419465fac47a8f81e12fb48c91d204851ab257108b5822167eed706bc340d6dc934cf637744fbc13953289fbd19f12413b627fcec373ffa2bae301da2794b1067476093941dd20872c626181b3f64677a0686cbc9cbfd26948d363892267f848820640a0a2d72a8ec56486c9a6f050753741172c6d48a0a9a0ceee3e4bd3bc8211c42919820641a0cc5f461c78150e7d776c24dfa8254ecd200e32d4125135bf2470eebce1ca142e809c5c7082946f7344a1a6db2f6cbd2f8e088324661ef121fac78e2d0bf1377ef62902ec5b5daf49f536cad596bd48b79e4a4052f8b86228146805436a26a348b601a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310b0091a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0318b931f2fd109463dc35529a34c309be2f69ec517b3350d35d17d9eb9ed2051a0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a09b42d04e00dcd19346ce2f08c108f85727fca76f6dc57e30da5d76ce8f531c9280a0ad34ceb1c793eb6ab9036cecf8c0a1239b9edba58f94890173098a17d9b7693ba0b3638fba61f44f70d5b5727baaf03c779ab269dff4a5bf83c15266f4b5380cffa00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa076094ead9021f5472bb12b03aeb521e09d71029dfa5dac90afa7cb44cbdfc5bd80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a0579a97aa89dbeb98396792baa31c4a7ea8e2f41da084140f07bb4bd655b72dd5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba82244a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62244b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be32244d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32244e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc12a448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2a44a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62a44b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be32a44e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc130093801").to_vec() + } + + fn success_update_client_continuous_input(&self) -> Vec>> { + vec![ + // checkpoint 4424 turnLength 8 target 0-4424 + vec![ + //4400 + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ae9080ae608f90463a0794978ac680964fb5ada43366fa4d33a490c93ec6893304ddee68a59f2cafabaa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a09f0bb93d54df1fcbfd84d4173496de9cff0f403319bbbaf15791ccde774b73d8a03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211308402625a008229a884669fb2e3b90223d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8048fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6ca7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98cb2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833309f8ae0fb860834538868d2c79371ead2f10fc7229fd3b3aaf1d7d8607fd7e1d2efba7df1008c105fdab4ad8029f86cfde1e3aa7dd24194fcf07502bb6c281fc3cbc08ad8cb467de57cbfd1bb93fabe72f77ece8f991a2b7a4d7fb301d54547c6cb4b612d06ff84882112ea042dfe9761fb9a677b088a868f237a171d511bea581f643844a1c98267902391882112fa0794978ac680964fb5ada43366fa4d33a490c93ec6893304ddee68a59f2cafaba80321f35c8454a2691a2efff6894cae6277ea06390978294fe0d10fe03f432fd07440d802ca0858a2d6138230b37d1a9148a3d76fbe8492854e637c9aad7494e3401a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa09696424e13500cdc742b049c6459c0bc4cb357eab5d9fb48a2e79787c8897a1fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211318402625a008084669fb2e6b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860b6de9ffe941751cd11463bbd4bde69d3bc2b79868f669f9e2c4c327f036e6d558b013469a91670607dd88d63dc50b95d00719e118a17e5b72418b6ae4bef7aebbcdaa44b79f8c0677ac32c71312d84db44e6e9216bd84fb97c7d0701a4a03431f84882112fa0794978ac680964fb5ada43366fa4d33a490c93ec6893304ddee68a59f2cafaba821130a09696424e13500cdc742b049c6459c0bc4cb357eab5d9fb48a2e79787c8897a1f80e5619874ecb4463f8d86981d939ddb4d0eaa151c6080c7067788e06699789d0a415e921b8824e8adc7907e5bbccec9373b22c7fe8a48527e9348aa957871b63300a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0e3aa9bc64f82ccd7e70ec415d73263d9da9f3bb44b78bed500033379df9be8aaa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211328402625a008084669fb2e9b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb86095a056c77bdeb59da26e665d69e75cc5667cd43df693a55f20f5f248483a3ce10cdd996b29c7fd6ba3f9e31cb4ac089c0b5bc13e77d83f17096d88f280b8d47ffd8b58b66bd760d0ccd4d26e0c2a7bb3ec168a06a815cfbdde9a2e18c32ac74ef848821130a09696424e13500cdc742b049c6459c0bc4cb357eab5d9fb48a2e79787c8897a1f821131a0e3aa9bc64f82ccd7e70ec415d73263d9da9f3bb44b78bed500033379df9be8aa80c04c6f70fa142c7486f7bed7e29a247f1203d58c7481c9aefef1193e6404112e32486f8d4dc8c7c558ae0b1bf860f6e05d425b7726ba7a4e2dac6e3e3eb83d3d00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310e8201a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea065b83aa9b59125f9b090432f556c6ff947b5708eb11ca5ea26342392860be00aa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a064c0a17f12a753c3fc032723866ac267ad8b7e05e7aa2e75bb680175d936617580a01a41c640130c53b3c90b1b5c691ed467218cee97aade5aac9306e72865851e27a004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0a1575ef06513a19d2a28390e83958d2a3ffe166b530255b0fb5559d33409914d80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a063a8a6161448a60a47ddbafa00899bed224e9f80072b35a1dbc64a82e85cd9b5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2244a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2244b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442244e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f83332a448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2a44b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442a44d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d22a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833330093808").to_vec(), + //4424 + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212d91e0ad5060ad206f9034fa07e83f283edaaa3f96ed0ea6eff394a8f33426be9f40cdf92ee1244c34773d578a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211488402625a008084669fb32bb90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860b6ed50c4b59a9e54e8e082fa735665d629f10488d2138f1e454b765ea16eca7571dbd7826e2b570b2905594f899fa2561977420047c4d053343146ed88df4ff667b9aa59679c3285dcccfa809647eb8ed2164b50f8e576fdc8f088cba74b6e98f848821146a08597c8d93294088beb70b3ec55ca00455f21c3c869f29a53a5a016f0ddc70490821147a07e83f283edaaa3f96ed0ea6eff394a8f33426be9f40cdf92ee1244c34773d578806c1bd063cda5cde68b7cdefa344815da1933ecd7212bfc3230cb37bc51d824156c969bfce6319e650e5adc96a133dc2759274b24bf5da3530648934500fe676b00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa06dc8edd393bb42e10868aa75eb0b4d891aec1c52940129e5ae1701b20f0922f4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211498402625a008084669fb32eb90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb8609181bd632b988883a8d359e589409e6930dc2526a3143bc4406c976d4946edc6a894648cd2aa4113fd6c91cb519bf3e10e17fbbca9102de604bcaa013e2d0709320530bef0b2002dd451cc8166a5b626224cf94abaa9d906ec474bd48a79beb7f848821147a07e83f283edaaa3f96ed0ea6eff394a8f33426be9f40cdf92ee1244c34773d578821148a06dc8edd393bb42e10868aa75eb0b4d891aec1c52940129e5ae1701b20f0922f480119ad821963837eaf154d653c8c35215e3cf8a7c48154b1ea6e85b9efadf3f301e60c91b19b77d8600e7297e6a6b9ef9433e7b890e06e03fc2c084d0c0c79d9f00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0298fc95dada993aa42f306441bd8d5c7631a08cb5d8358659445a4691f26a14da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000282114a8402625a008084669fb331b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860a11e6d8a9c037cada3344abb538da2d287ec129993e50e6fba2dae713071344075a255b9872edf6471a72733f5602d740f7a9e81adcf41451146f80197a3e09a5c88d80f2010284396cb0aa4e4022cf8a66f9d8cb015cc0d15ddfbf4b38e57ddf848821148a06dc8edd393bb42e10868aa75eb0b4d891aec1c52940129e5ae1701b20f0922f4821149a0298fc95dada993aa42f306441bd8d5c7631a08cb5d8358659445a4691f26a14d80de1e991caa78f9d4b979c96d3a74ec7c6f34343ba466294780a7f475a616b4930bedaffe245caaf1c87a505b3d7d8f492f786bf4e884823b0ab94e46e4baadf400a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310b0221a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea065b83aa9b59125f9b090432f556c6ff947b5708eb11ca5ea26342392860be00aa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a064c0a17f12a753c3fc032723866ac267ad8b7e05e7aa2e75bb680175d936617580a01a41c640130c53b3c90b1b5c691ed467218cee97aade5aac9306e72865851e27a004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0a1575ef06513a19d2a28390e83958d2a3ffe166b530255b0fb5559d33409914d80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a063a8a6161448a60a47ddbafa00899bed224e9f80072b35a1dbc64a82e85cd9b5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2244a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2244b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442244e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f83332a448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2a44b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442a44d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d22a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833330093808").to_vec(), + ], + // 4423 + vec![ + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ae9080ae608f90463a0794978ac680964fb5ada43366fa4d33a490c93ec6893304ddee68a59f2cafabaa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a09f0bb93d54df1fcbfd84d4173496de9cff0f403319bbbaf15791ccde774b73d8a03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211308402625a008229a884669fb2e3b90223d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8048fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6ca7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98cb2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833309f8ae0fb860834538868d2c79371ead2f10fc7229fd3b3aaf1d7d8607fd7e1d2efba7df1008c105fdab4ad8029f86cfde1e3aa7dd24194fcf07502bb6c281fc3cbc08ad8cb467de57cbfd1bb93fabe72f77ece8f991a2b7a4d7fb301d54547c6cb4b612d06ff84882112ea042dfe9761fb9a677b088a868f237a171d511bea581f643844a1c98267902391882112fa0794978ac680964fb5ada43366fa4d33a490c93ec6893304ddee68a59f2cafaba80321f35c8454a2691a2efff6894cae6277ea06390978294fe0d10fe03f432fd07440d802ca0858a2d6138230b37d1a9148a3d76fbe8492854e637c9aad7494e3401a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa09696424e13500cdc742b049c6459c0bc4cb357eab5d9fb48a2e79787c8897a1fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211318402625a008084669fb2e6b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860b6de9ffe941751cd11463bbd4bde69d3bc2b79868f669f9e2c4c327f036e6d558b013469a91670607dd88d63dc50b95d00719e118a17e5b72418b6ae4bef7aebbcdaa44b79f8c0677ac32c71312d84db44e6e9216bd84fb97c7d0701a4a03431f84882112fa0794978ac680964fb5ada43366fa4d33a490c93ec6893304ddee68a59f2cafaba821130a09696424e13500cdc742b049c6459c0bc4cb357eab5d9fb48a2e79787c8897a1f80e5619874ecb4463f8d86981d939ddb4d0eaa151c6080c7067788e06699789d0a415e921b8824e8adc7907e5bbccec9373b22c7fe8a48527e9348aa957871b63300a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0e3aa9bc64f82ccd7e70ec415d73263d9da9f3bb44b78bed500033379df9be8aaa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211328402625a008084669fb2e9b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb86095a056c77bdeb59da26e665d69e75cc5667cd43df693a55f20f5f248483a3ce10cdd996b29c7fd6ba3f9e31cb4ac089c0b5bc13e77d83f17096d88f280b8d47ffd8b58b66bd760d0ccd4d26e0c2a7bb3ec168a06a815cfbdde9a2e18c32ac74ef848821130a09696424e13500cdc742b049c6459c0bc4cb357eab5d9fb48a2e79787c8897a1f821131a0e3aa9bc64f82ccd7e70ec415d73263d9da9f3bb44b78bed500033379df9be8aa80c04c6f70fa142c7486f7bed7e29a247f1203d58c7481c9aefef1193e6404112e32486f8d4dc8c7c558ae0b1bf860f6e05d425b7726ba7a4e2dac6e3e3eb83d3d00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310e8201a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea065b83aa9b59125f9b090432f556c6ff947b5708eb11ca5ea26342392860be00aa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a064c0a17f12a753c3fc032723866ac267ad8b7e05e7aa2e75bb680175d936617580a01a41c640130c53b3c90b1b5c691ed467218cee97aade5aac9306e72865851e27a004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0a1575ef06513a19d2a28390e83958d2a3ffe166b530255b0fb5559d33409914d80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a063a8a6161448a60a47ddbafa00899bed224e9f80072b35a1dbc64a82e85cd9b5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2244a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2244b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442244e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f83332a448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2a44b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442a44d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d22a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833330093808").to_vec(), + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212d91e0ad5060ad206f9034fa08597c8d93294088beb70b3ec55ca00455f21c3c869f29a53a5a016f0ddc70490a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211478402625a008084669fb328b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860af92c5293ca4336704b31966a2d411532a7c9696f188dfce265be71340b5c8e3a3b34fa8d2684ea3a7f568e4d00ebd3613d00969b3b5ee28e218059dd9daa317232407168621b9ff0c29b10826b9e147d1e6581ef82eeffcaa2efc978d7bad64f848821145a0e322fe7afcc860264a85976dad2a256409bb3638003903326e3e5158ad95e83f821146a08597c8d93294088beb70b3ec55ca00455f21c3c869f29a53a5a016f0ddc70490808dc71db6edb508340d681faca3a54624171b62e4ed4639f3b1f67f954b87861c7686519390f671e919cb3f60fd1516ebefa7fea912ced5d6275e6797a3ccac1f00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa07e83f283edaaa3f96ed0ea6eff394a8f33426be9f40cdf92ee1244c34773d578a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211488402625a008084669fb32bb90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860b6ed50c4b59a9e54e8e082fa735665d629f10488d2138f1e454b765ea16eca7571dbd7826e2b570b2905594f899fa2561977420047c4d053343146ed88df4ff667b9aa59679c3285dcccfa809647eb8ed2164b50f8e576fdc8f088cba74b6e98f848821146a08597c8d93294088beb70b3ec55ca00455f21c3c869f29a53a5a016f0ddc70490821147a07e83f283edaaa3f96ed0ea6eff394a8f33426be9f40cdf92ee1244c34773d578806c1bd063cda5cde68b7cdefa344815da1933ecd7212bfc3230cb37bc51d824156c969bfce6319e650e5adc96a133dc2759274b24bf5da3530648934500fe676b00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa06dc8edd393bb42e10868aa75eb0b4d891aec1c52940129e5ae1701b20f0922f4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211498402625a008084669fb32eb90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb8609181bd632b988883a8d359e589409e6930dc2526a3143bc4406c976d4946edc6a894648cd2aa4113fd6c91cb519bf3e10e17fbbca9102de604bcaa013e2d0709320530bef0b2002dd451cc8166a5b626224cf94abaa9d906ec474bd48a79beb7f848821147a07e83f283edaaa3f96ed0ea6eff394a8f33426be9f40cdf92ee1244c34773d578821148a06dc8edd393bb42e10868aa75eb0b4d891aec1c52940129e5ae1701b20f0922f480119ad821963837eaf154d653c8c35215e3cf8a7c48154b1ea6e85b9efadf3f301e60c91b19b77d8600e7297e6a6b9ef9433e7b890e06e03fc2c084d0c0c79d9f00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310b0221a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea065b83aa9b59125f9b090432f556c6ff947b5708eb11ca5ea26342392860be00aa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a064c0a17f12a753c3fc032723866ac267ad8b7e05e7aa2e75bb680175d936617580a01a41c640130c53b3c90b1b5c691ed467218cee97aade5aac9306e72865851e27a004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0a1575ef06513a19d2a28390e83958d2a3ffe166b530255b0fb5559d33409914d80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a063a8a6161448a60a47ddbafa00899bed224e9f80072b35a1dbc64a82e85cd9b5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2244a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2244b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442244e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f83332a448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2a44b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442a44d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d22a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833330093808").to_vec(), + ], + // checkpoint 4627 turnLength 9 target 0-4700 + vec![ + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ae9080ae608f90463a00f2f3784c6d60d1be2666840114c0b20da860de6af0c718087cd4d1248c4de59a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a092fe9b87aac5e3e9d963a9176e28d4c71086d2c13b46ded73e0467a61f7a0fd7a03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211f88402625a008229a884669fb53bb90223d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e804a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98cb2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a44d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d2e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833304f8ae0fb860954dd9a7e6559e3f6f55f9ba10aaf0baac053ece467f77d6d42d204b629b5048d683376d02ce17945955458a8f30a9a601bf555c0283ff99075cc422edcc8ec964f161e6fd897999177c98dd733e8dfb6dc8085ca2b20af98022024c19abdc92f8488211f6a059332f01fb2eb9930f0e9fb5845396fc1815b2d1c4b59d02bf294601c8520e7c8211f7a00f2f3784c6d60d1be2666840114c0b20da860de6af0c718087cd4d1248c4de598071fda5fa2587d87bf54660696cadbc7ebdf31a245474525de5136c1ff874095a62294fd1b2ea25e84c3e402a7a3a23831f2629761ad7e2007b9d32f02346466c00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa07629a6e123fa3e2e2ea74419dda8270bd54d31fdc33f51bcebc845d86c462da4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211f98402625a008084669fb53eb90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860b98cdf6910246b1d63a21a58aaefd83776297f08ebd6226b34be9fe73aac50a2ee3aa920b67059563f60e94d1635ccb4146dce79aac8aa1b82541ab8624e86babd01e54c2205dbbfafe5e57be36a8c5c96b844db0f39fb2acc1914c5d838fa5bf8488211f7a00f2f3784c6d60d1be2666840114c0b20da860de6af0c718087cd4d1248c4de598211f8a07629a6e123fa3e2e2ea74419dda8270bd54d31fdc33f51bcebc845d86c462da4809ecf963edc51a77ac5a0a64d83e63c63289a2623cedc97e5a8c458f2fa54900677d1176db4c6911dedf7fd1c7e5f72c521c71d3c820adff16fd085dcaea6f60c01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa04efcea74c9f84fc35eb27c58b3b01263e2abe62131f720e24d1d2726abb9d777a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211fa8402625a008084669fb541b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860a5e737e760e4d3b6e4966678f49264cd84af64a21abfac165be7664ca2d8f604fc6b1dcf015c29c7a69ac381c3f3679c11328ac212b8be7348304cfc1dd821a7fa24f9a0c211d2bfeccc26fd2d352d72afb467cad2d974b0b3181437ccd4204bf8488211f8a07629a6e123fa3e2e2ea74419dda8270bd54d31fdc33f51bcebc845d86c462da48211f9a04efcea74c9f84fc35eb27c58b3b01263e2abe62131f720e24d1d2726abb9d77780ef69344959bf3a0cce0732ebb0a871676c381e77264b9eef8875c9bea16ea07812d4f290a701b4ba256800a7219f6413b27b367ebbb23686ac044a5f44af63c400a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310b0221a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0ded0ae13e1f14e98e291b7bc725f590e0208cd8aee5029e86999268a01dfa95aa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a064c0a17f12a753c3fc032723866ac267ad8b7e05e7aa2e75bb680175d936617580a03dc9ef066e7332efc09e4f620aab588d5465c1ed3b813c912928f1ffa44503a6a004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0a1575ef06513a19d2a28390e83958d2a3ffe166b530255b0fb5559d33409914d80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a063a8a6161448a60a47ddbafa00899bed224e9f80072b35a1dbc64a82e85cd9b5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba82244a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2244b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442244d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d22244e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f83332a448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2a44a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2a44b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833330043809") .to_vec(), + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212d91e0ad5060ad206f9034fa04405b2852348288eb937f08cf2d4bbf9eb3b93e0cc37abf5a2d66480e72b3f93a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028212138402625a008084669fb58cb90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860ac1a9ed39be5ee71e4b04d6685b84a6c8af9bd23cc2490c4a922ae7f9adaafbbd0b33a7ec7af34c439a74b8019fd837014791bd9cad48d4bdf969ef1aadc93c9b2b466845711e6c45f1c0a1625cdc262d9da55861bddb43b8f378560147bddc6f848821211a0c7eb18f17075bce2c6433c7067473a8aed41832321610cd4203ac2458767000b821212a04405b2852348288eb937f08cf2d4bbf9eb3b93e0cc37abf5a2d66480e72b3f93800003aa6dca4260b052409e2c2f21878d34bcab41aaf0fdca1b22b1ce22f0d2da56ccce3bc9b18fae5aa5df4a69f5b3078d2db98094dfef7a8724ebda8151425600a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa08a0f8318b4ebf3563cdebccbc1c5c9dc1631507e20b25ee82838b4200e7866dca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028212148402625a008084669fb58fb90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860a1c7de98d980f1f5a1c7809a50b9f7b5edb0b0a2c5021a66375cc76b7fb018516521a8e66e871e343d2c7f767c5ee320146dacde02ff88061077445b32f03c0b2b80a0b4b57add85a90574490bc78a588fc5fced38340c9bff33e724eb8add09f848821212a04405b2852348288eb937f08cf2d4bbf9eb3b93e0cc37abf5a2d66480e72b3f93821213a08a0f8318b4ebf3563cdebccbc1c5c9dc1631507e20b25ee82838b4200e7866dc808b54d4dd3dd7b680aff75622bf8e37c28ad9c1b1ebee259dc6059c2eeece574330af8f57dd8d6fcb180e4561f8fd178390d0cdeda778716f3bb0af65826ca9af01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa09249902fceede184ab056d38dbf0c5a7ef63efea6d806f9c4a4252858986eb0aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028212158402625a008084669fb592b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb86084b35063aa88712f15fecae44da0a94be292fbe0de1485357e4963d14536b4fd2068d58a65ef742bd8a6b21815c5b21304a518012f244d711157e18d45393d5b4eb414cde52929938890c912d362f894ec71df7bb1e29f0c5e3d6eb9976f1004f848821213a08a0f8318b4ebf3563cdebccbc1c5c9dc1631507e20b25ee82838b4200e7866dc821214a09249902fceede184ab056d38dbf0c5a7ef63efea6d806f9c4a4252858986eb0a808d9ab2b91f65aa6ead079f8b544dde4fa466d3586714e5da17f8f671599c5a5717b18d1811d6a3bfe5ccb1f6567b95cdc099a0f7d315a98e3199a268e5b5d53e00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310f8231a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0ded0ae13e1f14e98e291b7bc725f590e0208cd8aee5029e86999268a01dfa95aa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a064c0a17f12a753c3fc032723866ac267ad8b7e05e7aa2e75bb680175d936617580a03dc9ef066e7332efc09e4f620aab588d5465c1ed3b813c912928f1ffa44503a6a004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0a1575ef06513a19d2a28390e83958d2a3ffe166b530255b0fb5559d33409914d80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a063a8a6161448a60a47ddbafa00899bed224e9f80072b35a1dbc64a82e85cd9b5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba82244a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2244b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442244d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d22244e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f83332a448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2a44a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2a44b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833330043809").to_vec() + ], + // 4626 + vec![ + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ae9080ae608f90463a00f2f3784c6d60d1be2666840114c0b20da860de6af0c718087cd4d1248c4de59a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a092fe9b87aac5e3e9d963a9176e28d4c71086d2c13b46ded73e0467a61f7a0fd7a03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211f88402625a008229a884669fb53bb90223d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e804a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98cb2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a44d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d2e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833304f8ae0fb860954dd9a7e6559e3f6f55f9ba10aaf0baac053ece467f77d6d42d204b629b5048d683376d02ce17945955458a8f30a9a601bf555c0283ff99075cc422edcc8ec964f161e6fd897999177c98dd733e8dfb6dc8085ca2b20af98022024c19abdc92f8488211f6a059332f01fb2eb9930f0e9fb5845396fc1815b2d1c4b59d02bf294601c8520e7c8211f7a00f2f3784c6d60d1be2666840114c0b20da860de6af0c718087cd4d1248c4de598071fda5fa2587d87bf54660696cadbc7ebdf31a245474525de5136c1ff874095a62294fd1b2ea25e84c3e402a7a3a23831f2629761ad7e2007b9d32f02346466c00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa07629a6e123fa3e2e2ea74419dda8270bd54d31fdc33f51bcebc845d86c462da4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211f98402625a008084669fb53eb90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860b98cdf6910246b1d63a21a58aaefd83776297f08ebd6226b34be9fe73aac50a2ee3aa920b67059563f60e94d1635ccb4146dce79aac8aa1b82541ab8624e86babd01e54c2205dbbfafe5e57be36a8c5c96b844db0f39fb2acc1914c5d838fa5bf8488211f7a00f2f3784c6d60d1be2666840114c0b20da860de6af0c718087cd4d1248c4de598211f8a07629a6e123fa3e2e2ea74419dda8270bd54d31fdc33f51bcebc845d86c462da4809ecf963edc51a77ac5a0a64d83e63c63289a2623cedc97e5a8c458f2fa54900677d1176db4c6911dedf7fd1c7e5f72c521c71d3c820adff16fd085dcaea6f60c01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa04efcea74c9f84fc35eb27c58b3b01263e2abe62131f720e24d1d2726abb9d777a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211fa8402625a008084669fb541b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860a5e737e760e4d3b6e4966678f49264cd84af64a21abfac165be7664ca2d8f604fc6b1dcf015c29c7a69ac381c3f3679c11328ac212b8be7348304cfc1dd821a7fa24f9a0c211d2bfeccc26fd2d352d72afb467cad2d974b0b3181437ccd4204bf8488211f8a07629a6e123fa3e2e2ea74419dda8270bd54d31fdc33f51bcebc845d86c462da48211f9a04efcea74c9f84fc35eb27c58b3b01263e2abe62131f720e24d1d2726abb9d77780ef69344959bf3a0cce0732ebb0a871676c381e77264b9eef8875c9bea16ea07812d4f290a701b4ba256800a7219f6413b27b367ebbb23686ac044a5f44af63c400a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310b0221a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0ded0ae13e1f14e98e291b7bc725f590e0208cd8aee5029e86999268a01dfa95aa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a064c0a17f12a753c3fc032723866ac267ad8b7e05e7aa2e75bb680175d936617580a03dc9ef066e7332efc09e4f620aab588d5465c1ed3b813c912928f1ffa44503a6a004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0a1575ef06513a19d2a28390e83958d2a3ffe166b530255b0fb5559d33409914d80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a063a8a6161448a60a47ddbafa00899bed224e9f80072b35a1dbc64a82e85cd9b5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba82244a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2244b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442244d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d22244e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f83332a448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2a44a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2a44b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833330043809") .to_vec(), + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212d91e0ad5060ad206f9034fa0c7eb18f17075bce2c6433c7067473a8aed41832321610cd4203ac2458767000ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028212128402625a008084669fb589b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb86081f087223adcf0e52ec559804997c76b928c922d2b18303a53d5eb2d4aacc0c51c77b5cd3e549da81a1e59a0b00084c600b3a1479cc06c825b3c7483413f14c27b5e858233352b744b4366c64df4e2df2965b5bab6229b64aef58fbf16ea2547f848821210a007ae96eb397a1c4786191ed1666e2037a1cb789b7966d546174ff5c51a26cdea821211a0c7eb18f17075bce2c6433c7067473a8aed41832321610cd4203ac2458767000b800db71cfcf5f3efea5deb8887bc3b1490ac7eb950c9bdf0eb8fa866aa90b90ba54c85a0ff8a86247a2c4ecbaa5a6d7ec62f75fbd09bfbbc37f1b42f95c6c3e9d401a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa04405b2852348288eb937f08cf2d4bbf9eb3b93e0cc37abf5a2d66480e72b3f93a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028212138402625a008084669fb58cb90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860ac1a9ed39be5ee71e4b04d6685b84a6c8af9bd23cc2490c4a922ae7f9adaafbbd0b33a7ec7af34c439a74b8019fd837014791bd9cad48d4bdf969ef1aadc93c9b2b466845711e6c45f1c0a1625cdc262d9da55861bddb43b8f378560147bddc6f848821211a0c7eb18f17075bce2c6433c7067473a8aed41832321610cd4203ac2458767000b821212a04405b2852348288eb937f08cf2d4bbf9eb3b93e0cc37abf5a2d66480e72b3f93800003aa6dca4260b052409e2c2f21878d34bcab41aaf0fdca1b22b1ce22f0d2da56ccce3bc9b18fae5aa5df4a69f5b3078d2db98094dfef7a8724ebda8151425600a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa08a0f8318b4ebf3563cdebccbc1c5c9dc1631507e20b25ee82838b4200e7866dca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028212148402625a008084669fb58fb90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860a1c7de98d980f1f5a1c7809a50b9f7b5edb0b0a2c5021a66375cc76b7fb018516521a8e66e871e343d2c7f767c5ee320146dacde02ff88061077445b32f03c0b2b80a0b4b57add85a90574490bc78a588fc5fced38340c9bff33e724eb8add09f848821212a04405b2852348288eb937f08cf2d4bbf9eb3b93e0cc37abf5a2d66480e72b3f93821213a08a0f8318b4ebf3563cdebccbc1c5c9dc1631507e20b25ee82838b4200e7866dc808b54d4dd3dd7b680aff75622bf8e37c28ad9c1b1ebee259dc6059c2eeece574330af8f57dd8d6fcb180e4561f8fd178390d0cdeda778716f3bb0af65826ca9af01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310f8231a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0ded0ae13e1f14e98e291b7bc725f590e0208cd8aee5029e86999268a01dfa95aa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a064c0a17f12a753c3fc032723866ac267ad8b7e05e7aa2e75bb680175d936617580a03dc9ef066e7332efc09e4f620aab588d5465c1ed3b813c912928f1ffa44503a6a004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0a1575ef06513a19d2a28390e83958d2a3ffe166b530255b0fb5559d33409914d80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a063a8a6161448a60a47ddbafa00899bed224e9f80072b35a1dbc64a82e85cd9b5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba82244a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2244b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442244d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d22244e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f83332a448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2a44a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2a44b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833330043809").to_vec() + ], + // 4628 + vec![ + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ae9080ae608f90463a00f2f3784c6d60d1be2666840114c0b20da860de6af0c718087cd4d1248c4de59a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a092fe9b87aac5e3e9d963a9176e28d4c71086d2c13b46ded73e0467a61f7a0fd7a03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211f88402625a008229a884669fb53bb90223d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e804a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98cb2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a44d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d2e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833304f8ae0fb860954dd9a7e6559e3f6f55f9ba10aaf0baac053ece467f77d6d42d204b629b5048d683376d02ce17945955458a8f30a9a601bf555c0283ff99075cc422edcc8ec964f161e6fd897999177c98dd733e8dfb6dc8085ca2b20af98022024c19abdc92f8488211f6a059332f01fb2eb9930f0e9fb5845396fc1815b2d1c4b59d02bf294601c8520e7c8211f7a00f2f3784c6d60d1be2666840114c0b20da860de6af0c718087cd4d1248c4de598071fda5fa2587d87bf54660696cadbc7ebdf31a245474525de5136c1ff874095a62294fd1b2ea25e84c3e402a7a3a23831f2629761ad7e2007b9d32f02346466c00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa07629a6e123fa3e2e2ea74419dda8270bd54d31fdc33f51bcebc845d86c462da4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211f98402625a008084669fb53eb90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860b98cdf6910246b1d63a21a58aaefd83776297f08ebd6226b34be9fe73aac50a2ee3aa920b67059563f60e94d1635ccb4146dce79aac8aa1b82541ab8624e86babd01e54c2205dbbfafe5e57be36a8c5c96b844db0f39fb2acc1914c5d838fa5bf8488211f7a00f2f3784c6d60d1be2666840114c0b20da860de6af0c718087cd4d1248c4de598211f8a07629a6e123fa3e2e2ea74419dda8270bd54d31fdc33f51bcebc845d86c462da4809ecf963edc51a77ac5a0a64d83e63c63289a2623cedc97e5a8c458f2fa54900677d1176db4c6911dedf7fd1c7e5f72c521c71d3c820adff16fd085dcaea6f60c01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa04efcea74c9f84fc35eb27c58b3b01263e2abe62131f720e24d1d2726abb9d777a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211fa8402625a008084669fb541b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860a5e737e760e4d3b6e4966678f49264cd84af64a21abfac165be7664ca2d8f604fc6b1dcf015c29c7a69ac381c3f3679c11328ac212b8be7348304cfc1dd821a7fa24f9a0c211d2bfeccc26fd2d352d72afb467cad2d974b0b3181437ccd4204bf8488211f8a07629a6e123fa3e2e2ea74419dda8270bd54d31fdc33f51bcebc845d86c462da48211f9a04efcea74c9f84fc35eb27c58b3b01263e2abe62131f720e24d1d2726abb9d77780ef69344959bf3a0cce0732ebb0a871676c381e77264b9eef8875c9bea16ea07812d4f290a701b4ba256800a7219f6413b27b367ebbb23686ac044a5f44af63c400a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310b0221a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0ded0ae13e1f14e98e291b7bc725f590e0208cd8aee5029e86999268a01dfa95aa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a064c0a17f12a753c3fc032723866ac267ad8b7e05e7aa2e75bb680175d936617580a03dc9ef066e7332efc09e4f620aab588d5465c1ed3b813c912928f1ffa44503a6a004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0a1575ef06513a19d2a28390e83958d2a3ffe166b530255b0fb5559d33409914d80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a063a8a6161448a60a47ddbafa00899bed224e9f80072b35a1dbc64a82e85cd9b5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba82244a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2244b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442244d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d22244e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f83332a448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2a44a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2a44b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833330043809") .to_vec(), + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212d91e0ad5060ad206f9034fa08a0f8318b4ebf3563cdebccbc1c5c9dc1631507e20b25ee82838b4200e7866dca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028212148402625a008084669fb58fb90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860a1c7de98d980f1f5a1c7809a50b9f7b5edb0b0a2c5021a66375cc76b7fb018516521a8e66e871e343d2c7f767c5ee320146dacde02ff88061077445b32f03c0b2b80a0b4b57add85a90574490bc78a588fc5fced38340c9bff33e724eb8add09f848821212a04405b2852348288eb937f08cf2d4bbf9eb3b93e0cc37abf5a2d66480e72b3f93821213a08a0f8318b4ebf3563cdebccbc1c5c9dc1631507e20b25ee82838b4200e7866dc808b54d4dd3dd7b680aff75622bf8e37c28ad9c1b1ebee259dc6059c2eeece574330af8f57dd8d6fcb180e4561f8fd178390d0cdeda778716f3bb0af65826ca9af01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa09249902fceede184ab056d38dbf0c5a7ef63efea6d806f9c4a4252858986eb0aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028212158402625a008084669fb592b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb86084b35063aa88712f15fecae44da0a94be292fbe0de1485357e4963d14536b4fd2068d58a65ef742bd8a6b21815c5b21304a518012f244d711157e18d45393d5b4eb414cde52929938890c912d362f894ec71df7bb1e29f0c5e3d6eb9976f1004f848821213a08a0f8318b4ebf3563cdebccbc1c5c9dc1631507e20b25ee82838b4200e7866dc821214a09249902fceede184ab056d38dbf0c5a7ef63efea6d806f9c4a4252858986eb0a808d9ab2b91f65aa6ead079f8b544dde4fa466d3586714e5da17f8f671599c5a5717b18d1811d6a3bfe5ccb1f6567b95cdc099a0f7d315a98e3199a268e5b5d53e00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0914c3fa83e1f679338195c58ea19dfab85f1e37ddb8bdb6e98a4f0a7a621575ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028212168402625a008084669fb595b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860a82b11ac3a16da80fe96338070479d843581fc96b1ec7e674034ff16b326f672b7276e0572d09778cbab20274751280e082f56b84a2fa69a3d4effeaa434e24bb91b2deac65ba30d81e269bdcd58681cece65fb43efdabf39feb8577d98a3979f848821214a09249902fceede184ab056d38dbf0c5a7ef63efea6d806f9c4a4252858986eb0a821215a0914c3fa83e1f679338195c58ea19dfab85f1e37ddb8bdb6e98a4f0a7a621575e805347706cb6777f5cce4f9970d4106b540bd37feb0ebc269cbcae2cabe2eede766cf8c829182db84d31f928ba050a38305a665985a950a83604c2e3a857ee74f801a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310f8231a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0ded0ae13e1f14e98e291b7bc725f590e0208cd8aee5029e86999268a01dfa95aa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a064c0a17f12a753c3fc032723866ac267ad8b7e05e7aa2e75bb680175d936617580a03dc9ef066e7332efc09e4f620aab588d5465c1ed3b813c912928f1ffa44503a6a004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0a1575ef06513a19d2a28390e83958d2a3ffe166b530255b0fb5559d33409914d80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a063a8a6161448a60a47ddbafa00899bed224e9f80072b35a1dbc64a82e85cd9b5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba82244a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2244b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442244d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d22244e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f83332a448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2a44a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2a44b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833330043809").to_vec() + ], + // 4799 + vec![ + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ae9080ae608f90463a00f2f3784c6d60d1be2666840114c0b20da860de6af0c718087cd4d1248c4de59a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a092fe9b87aac5e3e9d963a9176e28d4c71086d2c13b46ded73e0467a61f7a0fd7a03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211f88402625a008229a884669fb53bb90223d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e804a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98cb2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a44d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d2e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833304f8ae0fb860954dd9a7e6559e3f6f55f9ba10aaf0baac053ece467f77d6d42d204b629b5048d683376d02ce17945955458a8f30a9a601bf555c0283ff99075cc422edcc8ec964f161e6fd897999177c98dd733e8dfb6dc8085ca2b20af98022024c19abdc92f8488211f6a059332f01fb2eb9930f0e9fb5845396fc1815b2d1c4b59d02bf294601c8520e7c8211f7a00f2f3784c6d60d1be2666840114c0b20da860de6af0c718087cd4d1248c4de598071fda5fa2587d87bf54660696cadbc7ebdf31a245474525de5136c1ff874095a62294fd1b2ea25e84c3e402a7a3a23831f2629761ad7e2007b9d32f02346466c00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa07629a6e123fa3e2e2ea74419dda8270bd54d31fdc33f51bcebc845d86c462da4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211f98402625a008084669fb53eb90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860b98cdf6910246b1d63a21a58aaefd83776297f08ebd6226b34be9fe73aac50a2ee3aa920b67059563f60e94d1635ccb4146dce79aac8aa1b82541ab8624e86babd01e54c2205dbbfafe5e57be36a8c5c96b844db0f39fb2acc1914c5d838fa5bf8488211f7a00f2f3784c6d60d1be2666840114c0b20da860de6af0c718087cd4d1248c4de598211f8a07629a6e123fa3e2e2ea74419dda8270bd54d31fdc33f51bcebc845d86c462da4809ecf963edc51a77ac5a0a64d83e63c63289a2623cedc97e5a8c458f2fa54900677d1176db4c6911dedf7fd1c7e5f72c521c71d3c820adff16fd085dcaea6f60c01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa04efcea74c9f84fc35eb27c58b3b01263e2abe62131f720e24d1d2726abb9d777a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211fa8402625a008084669fb541b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860a5e737e760e4d3b6e4966678f49264cd84af64a21abfac165be7664ca2d8f604fc6b1dcf015c29c7a69ac381c3f3679c11328ac212b8be7348304cfc1dd821a7fa24f9a0c211d2bfeccc26fd2d352d72afb467cad2d974b0b3181437ccd4204bf8488211f8a07629a6e123fa3e2e2ea74419dda8270bd54d31fdc33f51bcebc845d86c462da48211f9a04efcea74c9f84fc35eb27c58b3b01263e2abe62131f720e24d1d2726abb9d77780ef69344959bf3a0cce0732ebb0a871676c381e77264b9eef8875c9bea16ea07812d4f290a701b4ba256800a7219f6413b27b367ebbb23686ac044a5f44af63c400a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310b0221a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0ded0ae13e1f14e98e291b7bc725f590e0208cd8aee5029e86999268a01dfa95aa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a064c0a17f12a753c3fc032723866ac267ad8b7e05e7aa2e75bb680175d936617580a03dc9ef066e7332efc09e4f620aab588d5465c1ed3b813c912928f1ffa44503a6a004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0a1575ef06513a19d2a28390e83958d2a3ffe166b530255b0fb5559d33409914d80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a063a8a6161448a60a47ddbafa00899bed224e9f80072b35a1dbc64a82e85cd9b5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba82244a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2244b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442244d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d22244e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f83332a448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2a44a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2a44b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833330043809") .to_vec(), + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ad5060ad206f9034fa09087686190c6eae842761bf3b6c0299e4573536cdf4a277e930ef5f1488cb88fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e04db2de85453e0936b441c339a26d10cfa71b50a056225dbe337930eae2e5053ccbde08ae2b963fafa0682f472b32189a8789c3b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028212bf8402625a008084669fb790b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860b0f4fb9a9c9970ba0b13b21c6605cd72939c2dd5c87b39aca58c85dbbc15a41496bab85a11306d082dd978e35055794105086b2eefd3cced77558a41c7475bb401baf50c87e1d5fb07a93a2d046add70bbe045de27ccad5be3e8e142febab17cf8488212bda03cdba57c5f1e6130e71dfccc752694035c8e9bbbfbb4bffc6fbacfa653a217dc8212bea09087686190c6eae842761bf3b6c0299e4573536cdf4a277e930ef5f1488cb88f803e96ae1c69b70b960305eccc4b09f9a8776698f26e4f0087820a1e0a9084e38a2f6aa9ba3617e610755529339dcafcde4abc6e3987ba76ca2fbadd5423353ac201a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ae9080ae608f90463a00cd675d1a4f59cea079078246ed698a21e8873ac3454dab0c6bc71ec74433dd0a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a005c8bb760447e318fc3c964a6a047a38074a8a8acd630f13e9cb6290f6c917cea0ba5df750e02baac2fe6eed41dccdda6ddd9ccbbcdbab113bcd20ce86955fbe70a03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028212c08402625a008229a884669fb793b90223d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8048fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6ca7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98cb2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a44d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d206f8ae0fb860ad71337b4162caed9ffc51756eae682706a96abbc333e5f27767873bd3ff16b0a03b259db94947c8f1057d2dcc4caabf06847e9b5bccd843f040615d120008f1aa1833d22cac07e325b5d913a30e18248b77ca20cb942816d48c4c3e4d099fecf8488212bea09087686190c6eae842761bf3b6c0299e4573536cdf4a277e930ef5f1488cb88f8212bfa00cd675d1a4f59cea079078246ed698a21e8873ac3454dab0c6bc71ec74433dd080ca647eb84f4f9e06dbb5f17ce0bb252adf3fde1b61093c9db6b013f6eec88ebe2e41043bc19762ee36174b91d0383950cbadc8a51106cbc3d1ba5d874208ef9601a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0d78e550d546599d0e5d25a6280d42634285eeed5b68f25692b5ee8bfde9528a2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a005c8bb760447e318fc3c964a6a047a38074a8a8acd630f13e9cb6290f6c917cea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028212c18402625a008084669fb796b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860a60bfe671bd13c252b237b4222a361b19d89cfd5c58b6be3330a73b24b6d352afcbbf2cf300eeba1fe49fea61f76a21a03665f94ad81ec9bd474c937f4f143bc38f822843c41b61bd3ecd4844781bf8073ea0411cafaa9f77a421eeb4c0964a9f8488212bfa00cd675d1a4f59cea079078246ed698a21e8873ac3454dab0c6bc71ec74433dd08212c0a0d78e550d546599d0e5d25a6280d42634285eeed5b68f25692b5ee8bfde9528a280dfc0cd3dc16a57fe25955fb0df9304379e816659a89562c52a8a54e7534857f63f792f101cc37fae501197a4d7c59e9130fa65b790f35ea4b154ab75a9abd78b01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310f8231a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0ded0ae13e1f14e98e291b7bc725f590e0208cd8aee5029e86999268a01dfa95aa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a064c0a17f12a753c3fc032723866ac267ad8b7e05e7aa2e75bb680175d936617580a03dc9ef066e7332efc09e4f620aab588d5465c1ed3b813c912928f1ffa44503a6a004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0a1575ef06513a19d2a28390e83958d2a3ffe166b530255b0fb5559d33409914d80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a063a8a6161448a60a47ddbafa00899bed224e9f80072b35a1dbc64a82e85cd9b5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba82244a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2244b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442244d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d22244e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f83332a448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2a44a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2a44b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833330043809").to_vec() + ], + // checkpoint 2009 turnLength 3 target 0-2009 + vec![ + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ae9080ae608f90463a052c7f905de108f036db9b2315750c84d6c815f34b57595f27b8b4b849c7d7b4fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada0759cb1ebd68321866dc7681de12480917ad2d8995c3b6608b2c9c4a103fc519da05b4725d6a87fc261b989d40320187202c0a03ad275b6d3948bf6dcfca79386b1a03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028207d08402625a008229a88466a227a7b90223d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2f048fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ffa7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b6d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b3e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc105f8ae0fb860946bd01663fe1ca7e95450b9199fa5253ccaad23be73d52793df5f453cb20de1ff51ab6186d39fbee1c63ce1b7581b550a740a785d66e71a586085f0c32ea8abca557bd7d39269b863e6d6cc94d316e53e221470adfea1fe00606ed0ae517232f8488207cea0e52d65a5e0d00748aa43600e083afd974407ce2054e7822a2f9c8a730f37316d8207cfa052c7f905de108f036db9b2315750c84d6c815f34b57595f27b8b4b849c7d7b4f80bb983b9893f0543f575bf6a348da8cc0d7ee769012d44b5bf0f2de1439fab0987ce564285e70ad18d66580082f14da2193a879e16efda9e0ff0524211a85533d00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0a9e00a112aeb3e91b86e95511018df2047cd9984ace5c86f085b77d55e3486dda01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0759cb1ebd68321866dc7681de12480917ad2d8995c3b6608b2c9c4a103fc519da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028207d18402625a00808466a227aab90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb8608c4d41718a421559d4c91b9285ffd53c001c528f2696f387802a508c427ef96d731e73b81c0e5679c887d51ba794ad8e0332a29b05d21f4a436b11a274cae8335ebd066d8ff7244a3902e583f4a3a4fe347805f42d9cf272db93c12eb19597baf8488207cfa052c7f905de108f036db9b2315750c84d6c815f34b57595f27b8b4b849c7d7b4f8207d0a0a9e00a112aeb3e91b86e95511018df2047cd9984ace5c86f085b77d55e3486dd800d29d848de30c1a0ad08ffd9ecdd67403f152fc8f1786617775e2db93ec3d5073c5d1f74725f091f39f09109341d05b0db02df59b2f5d7b825451b1b9c61a48501a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa01caa266e53b23711a9a0845389294f5e4a445697737e820dea91d743e62eca5da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0759cb1ebd68321866dc7681de12480917ad2d8995c3b6608b2c9c4a103fc519da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028207d28402625a00808466a227adb90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860a76b14b8487cef51b8ee943af2386c8ef6fa60a56b375957d200c9b429f65a7206e85bd9965f63dd3f696bf722b1624e0c554ea89d453e56ccc528a050adad08143bd761ca80b7e9c172aa9c4d58b5e21ebd0e2c83f6ce0502855528d7acd7e4f8488207d0a0a9e00a112aeb3e91b86e95511018df2047cd9984ace5c86f085b77d55e3486dd8207d1a01caa266e53b23711a9a0845389294f5e4a445697737e820dea91d743e62eca5d80669abb81f040cc64c11e2bf33901138b269f0b720fa09d6ff00dc4628dbed8c75e6a1e41a90cf1d57fa472cbeb656168a3c6b800d8244324c072f6e3f30468e300a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310880e1a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea067ecb9b82d40265c310eaf00763b0fed54dfdf689ae4945f705b329f2b42b3dba0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a0c5efde1c8c860b17515432d64ac679d48902bea9421ecdc4e4156068c61fafb180a0ad34ceb1c793eb6ab9036cecf8c0a1239b9edba58f94890173098a17d9b7693ba0f34dd8753d794952d0235df0a1d2b415d55ef60c393c5a197281bfc8a5bdf681a00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa076094ead9021f5472bb12b03aeb521e09d71029dfa5dac90afa7cb44cbdfc5bd80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a0579a97aa89dbeb98396792baa31c4a7ea8e2f41da084140f07bb4bd655b72dd5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2244a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62244d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32244e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc12a448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2a44a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62a44b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be32a44d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b330053803") .to_vec(), + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212d91e0ad5060ad206f9034fa0f79e25ed6285179d4d82ea454695d38ba361acf43ea26f3fc5a8451016cb253fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a0759cb1ebd68321866dc7681de12480917ad2d8995c3b6608b2c9c4a103fc519da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028207d98402625a00808466a227c2b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860b93767a1a8005d8b3a0874bfc7808c59f3bc1b8444778307cb7d09bb3f8c43b32b5117df9c65ae4843d54fdbf40d382d1896574b3ad8a8f6acefb85686be61ce695c50e85232e3dc46a470e96e15f0a44282d41afd36ee9d6fe6ff6336f0f8eef8488207d7a0d79ba847026ce12a6ea07610d3eba41085267b91591e43dbdbb1d760a6ccc1bc8207d8a0f79e25ed6285179d4d82ea454695d38ba361acf43ea26f3fc5a8451016cb253f800477cca1964dd1bd73f4eb278d349cd6562a8106fbcbb541116770ea44cc605f4aeda07ba3389b0ffbf0e27d018c326d5a7871ef70490ba9c26afb8e6d60f5be01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0ef048929be37be72886019d6d983ea0296a0271243e09291fe2f84309b030a1ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0759cb1ebd68321866dc7681de12480917ad2d8995c3b6608b2c9c4a103fc519da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028207da8402625a00808466a227c5b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb86086872e2c9a12298026a3bf5c4575de14e383f741a5a46101c3892b2fd90a84ba775a11d5c03e2050884c3345ef7cfc4514e06f138c30bd7c54eeb1a7cd2b8ff4652701ed4b6051b681794fe4800efcbecd768d8de9f28df1eb04811e002b5240f8488207d8a0f79e25ed6285179d4d82ea454695d38ba361acf43ea26f3fc5a8451016cb253f8207d9a0ef048929be37be72886019d6d983ea0296a0271243e09291fe2f84309b030a1c801e2f5d814381948bc333a97e399a32b88d4b50a0419ef62931e983b5c501a9d267f56fb47de7c64cee7352326071167857213c8d3caa9987bef03e432c4b953a00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0bab45689cabc3dfe931b2b2b647ec15e80258192c1eea52a205563bce1b39139a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0759cb1ebd68321866dc7681de12480917ad2d8995c3b6608b2c9c4a103fc519da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028207db8402625a00808466a227c8b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860a15832c489e5010025858454cfcf8de1d8625eb1a4a499efbed42e968a6f65439ae14f3b3b47101c085525ea25ef303a06717103df3a0913be834d8548570427acb6c4e5dffacdcbe323a006f609410c102ddcd053611833cae51b80dc524a60f8488207d9a0ef048929be37be72886019d6d983ea0296a0271243e09291fe2f84309b030a1c8207daa0bab45689cabc3dfe931b2b2b647ec15e80258192c1eea52a205563bce1b3913980c15c4f11222b5db54721e5826c8dd0842631845408609dc6ebede765c6fa4b557ecc12f574622012886811d864b86b1b620833334af52e1d773c40f49381ef0200a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310d00f1a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea067ecb9b82d40265c310eaf00763b0fed54dfdf689ae4945f705b329f2b42b3dba0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a0c5efde1c8c860b17515432d64ac679d48902bea9421ecdc4e4156068c61fafb180a0ad34ceb1c793eb6ab9036cecf8c0a1239b9edba58f94890173098a17d9b7693ba0f34dd8753d794952d0235df0a1d2b415d55ef60c393c5a197281bfc8a5bdf681a00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa076094ead9021f5472bb12b03aeb521e09d71029dfa5dac90afa7cb44cbdfc5bd80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a0579a97aa89dbeb98396792baa31c4a7ea8e2f41da084140f07bb4bd655b72dd5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2244a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62244d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32244e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc12a448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2a44a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62a44b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be32a44d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b330053803").to_vec() + ], + // 2008 + vec![ + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ae9080ae608f90463a052c7f905de108f036db9b2315750c84d6c815f34b57595f27b8b4b849c7d7b4fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada0759cb1ebd68321866dc7681de12480917ad2d8995c3b6608b2c9c4a103fc519da05b4725d6a87fc261b989d40320187202c0a03ad275b6d3948bf6dcfca79386b1a03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028207d08402625a008229a88466a227a7b90223d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2f048fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ffa7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b6d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b3e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc105f8ae0fb860946bd01663fe1ca7e95450b9199fa5253ccaad23be73d52793df5f453cb20de1ff51ab6186d39fbee1c63ce1b7581b550a740a785d66e71a586085f0c32ea8abca557bd7d39269b863e6d6cc94d316e53e221470adfea1fe00606ed0ae517232f8488207cea0e52d65a5e0d00748aa43600e083afd974407ce2054e7822a2f9c8a730f37316d8207cfa052c7f905de108f036db9b2315750c84d6c815f34b57595f27b8b4b849c7d7b4f80bb983b9893f0543f575bf6a348da8cc0d7ee769012d44b5bf0f2de1439fab0987ce564285e70ad18d66580082f14da2193a879e16efda9e0ff0524211a85533d00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0a9e00a112aeb3e91b86e95511018df2047cd9984ace5c86f085b77d55e3486dda01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0759cb1ebd68321866dc7681de12480917ad2d8995c3b6608b2c9c4a103fc519da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028207d18402625a00808466a227aab90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb8608c4d41718a421559d4c91b9285ffd53c001c528f2696f387802a508c427ef96d731e73b81c0e5679c887d51ba794ad8e0332a29b05d21f4a436b11a274cae8335ebd066d8ff7244a3902e583f4a3a4fe347805f42d9cf272db93c12eb19597baf8488207cfa052c7f905de108f036db9b2315750c84d6c815f34b57595f27b8b4b849c7d7b4f8207d0a0a9e00a112aeb3e91b86e95511018df2047cd9984ace5c86f085b77d55e3486dd800d29d848de30c1a0ad08ffd9ecdd67403f152fc8f1786617775e2db93ec3d5073c5d1f74725f091f39f09109341d05b0db02df59b2f5d7b825451b1b9c61a48501a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa01caa266e53b23711a9a0845389294f5e4a445697737e820dea91d743e62eca5da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0759cb1ebd68321866dc7681de12480917ad2d8995c3b6608b2c9c4a103fc519da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028207d28402625a00808466a227adb90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860a76b14b8487cef51b8ee943af2386c8ef6fa60a56b375957d200c9b429f65a7206e85bd9965f63dd3f696bf722b1624e0c554ea89d453e56ccc528a050adad08143bd761ca80b7e9c172aa9c4d58b5e21ebd0e2c83f6ce0502855528d7acd7e4f8488207d0a0a9e00a112aeb3e91b86e95511018df2047cd9984ace5c86f085b77d55e3486dd8207d1a01caa266e53b23711a9a0845389294f5e4a445697737e820dea91d743e62eca5d80669abb81f040cc64c11e2bf33901138b269f0b720fa09d6ff00dc4628dbed8c75e6a1e41a90cf1d57fa472cbeb656168a3c6b800d8244324c072f6e3f30468e300a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310880e1a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea067ecb9b82d40265c310eaf00763b0fed54dfdf689ae4945f705b329f2b42b3dba0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a0c5efde1c8c860b17515432d64ac679d48902bea9421ecdc4e4156068c61fafb180a0ad34ceb1c793eb6ab9036cecf8c0a1239b9edba58f94890173098a17d9b7693ba0f34dd8753d794952d0235df0a1d2b415d55ef60c393c5a197281bfc8a5bdf681a00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa076094ead9021f5472bb12b03aeb521e09d71029dfa5dac90afa7cb44cbdfc5bd80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a0579a97aa89dbeb98396792baa31c4a7ea8e2f41da084140f07bb4bd655b72dd5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2244a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62244d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32244e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc12a448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2a44a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62a44b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be32a44d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b330053803") .to_vec(), + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212d91e0ad5060ad206f9034fa06160e6e45530a49dace82ba1afbd5dcf48935b0d2090cccd9bf47c44845f38e7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a0759cb1ebd68321866dc7681de12480917ad2d8995c3b6608b2c9c4a103fc519da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028207d78402625a00808466a227bcb90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860893ded20ad4b9b5a1c1daee9dfee2737bff4b7cdceec843f770b71ab84eedddecfcc6caf6725e5416d69a44f433ed22814fb9e1119c52bc93ea90e6b98c836f6572ccdbce53a88ffe7efb7c41ed4a3738230587aa4d0a21570246929c612ab4cf8488207d5a073df87c23945fc6a74d8a01b98e951e97717b79518aeb760e443b99b1549f8fc8207d6a06160e6e45530a49dace82ba1afbd5dcf48935b0d2090cccd9bf47c44845f38e7805d589b186fa54113764c5538bc8313392eb38d8abb5af2b1c5e7996e518d91ef39963c53497c0bd54db8224a2d60bd12a4a1d225108972c3be767dbdc120535101a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0d79ba847026ce12a6ea07610d3eba41085267b91591e43dbdbb1d760a6ccc1bca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a0759cb1ebd68321866dc7681de12480917ad2d8995c3b6608b2c9c4a103fc519da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028207d88402625a00808466a227bfb90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb8608b07302849be12f3e300e814465d8c2e56dc5724c1c077959ea910216addab2350cb5049826d99ae43052b23411a1c4b0e62f8683599781474841c690ee79c922665e3bde99c1d226b19c3aa98b36aa368a90616205cb0eedbd7ca534518e650f8488207d6a06160e6e45530a49dace82ba1afbd5dcf48935b0d2090cccd9bf47c44845f38e78207d7a0d79ba847026ce12a6ea07610d3eba41085267b91591e43dbdbb1d760a6ccc1bc80f7c8bf9ff3e2623dbce227b9ab7c6168151a45d3bac0e4e7a8f56c8521b5ecfe7271dcc6f956c435e7b77a6d3fc5a1b03c8d99230b3aeef32e62025a511941e400a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0f79e25ed6285179d4d82ea454695d38ba361acf43ea26f3fc5a8451016cb253fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7876ea32e7a748c697d01345145485561305b24a0759cb1ebd68321866dc7681de12480917ad2d8995c3b6608b2c9c4a103fc519da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028207d98402625a00808466a227c2b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860b93767a1a8005d8b3a0874bfc7808c59f3bc1b8444778307cb7d09bb3f8c43b32b5117df9c65ae4843d54fdbf40d382d1896574b3ad8a8f6acefb85686be61ce695c50e85232e3dc46a470e96e15f0a44282d41afd36ee9d6fe6ff6336f0f8eef8488207d7a0d79ba847026ce12a6ea07610d3eba41085267b91591e43dbdbb1d760a6ccc1bc8207d8a0f79e25ed6285179d4d82ea454695d38ba361acf43ea26f3fc5a8451016cb253f800477cca1964dd1bd73f4eb278d349cd6562a8106fbcbb541116770ea44cc605f4aeda07ba3389b0ffbf0e27d018c326d5a7871ef70490ba9c26afb8e6d60f5be01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310d00f1a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea067ecb9b82d40265c310eaf00763b0fed54dfdf689ae4945f705b329f2b42b3dba0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a0c5efde1c8c860b17515432d64ac679d48902bea9421ecdc4e4156068c61fafb180a0ad34ceb1c793eb6ab9036cecf8c0a1239b9edba58f94890173098a17d9b7693ba0f34dd8753d794952d0235df0a1d2b415d55ef60c393c5a197281bfc8a5bdf681a00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa076094ead9021f5472bb12b03aeb521e09d71029dfa5dac90afa7cb44cbdfc5bd80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a0579a97aa89dbeb98396792baa31c4a7ea8e2f41da084140f07bb4bd655b72dd5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2244a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62244d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32244e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc12a448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2a44a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62a44b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be32a44d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b330053803").to_vec() + ], + //checkpoint 2215 turnLength 5 target 0-2215 + vec![ + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ae9080ae608f90463a0c13597cb89679cf0b6f2ba3e0ae0781e5ec72c8f839c11083d6704d765137011a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca00bf9dee767e66678856f4c62a62515f54a39ebd7cb57ccb04ed25a22eff7065ba03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208988402625a008229a88466a229ffb90223d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2f048fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ffb2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be3d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b3e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc108f8ae0fb860a41bc57efe7ace714408c524070ad0e41bd17cb44f1367c23d64507edd2f94a804b86ad9f326e5fd7ff2646a77811d4013be08d719f6f24a81bf8ffae796c2c8238c79574ae05967517a1d194d27ae6f410c991e06d6431b490cc1826a9faa51f848820896a031f2ac651e45ab653e7a49287e7ca9754bea2e8e8dc87ea8062a6d43e4c9033f820897a0c13597cb89679cf0b6f2ba3e0ae0781e5ec72c8f839c11083d6704d765137011807a5af307aee11ef5106ca8d8a1a8596e48dc2ffcc3d0797e6ad57cbe8da519a8224042fdabede179427ba5021fa621d46b0cb8fcf285ee78cb0ba18dc7e325e701a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0ac8875032a5bec1f6b3d2e91c9f082e6a8ecbd326126a1a3bc6ecb14c3a4c1d0a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208998402625a00808466a22a02b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860ad4541e9b8a1c3d0def1a3f2d6d353c1d18f8c3d84822e29b413d5fa1fb77ee303add7c1441f7ac6a60e13f0b649483b105859b56e224feb6133a246fa60338e146d5747265994759964d4101d57914d4f3f00c380ff9b91dcb676851917880ff848820897a0c13597cb89679cf0b6f2ba3e0ae0781e5ec72c8f839c11083d6704d765137011820898a0ac8875032a5bec1f6b3d2e91c9f082e6a8ecbd326126a1a3bc6ecb14c3a4c1d0800e69a592db1d57d38c94298eff1ba8209e2a4b7b45b0c05b4d23c894b1c3d9285d446ee4d885a42a33b101c4ac7307f70b8173d5c89a67bafe8795ac3203449200a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0b1d096fbb6737a689f80e8e2f48811add6d9d6ec5cc631cb04a9a8dae0a562b4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000282089a8402625a00808466a22a05b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860a1f04d66e852eae33aeaf6a2b1a08b223f61e8a765894f9cdfbc6ac8aa0c04314df54fd0b98e14d2081c66fc5c49e162086853717104f1b5296adbba0b75643b00587131a47060e9e588ae216887576f41b6ea2e586615116bb46f6c40be812bf848820898a0ac8875032a5bec1f6b3d2e91c9f082e6a8ecbd326126a1a3bc6ecb14c3a4c1d0820899a0b1d096fbb6737a689f80e8e2f48811add6d9d6ec5cc631cb04a9a8dae0a562b480c2efdccaf70cac8ec2926f52473dd4c3b23004bbde1cb1f61ddcfa06deae348d3aa81b0237708debe61dadf589e79d9520f2011e8f8812cdfd1a60af3f4d8b6e01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310d00f1a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0273c6048b21e7d25636156a707b0be6ba081bcf7381f9b5019580f5aa70369e2a0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a033ff9ba3990e4af75e9e1a6beb627bfc13f4bb7a788fb8ce61c8e90abacfcc5080a0ad34ceb1c793eb6ab9036cecf8c0a1239b9edba58f94890173098a17d9b7693ba0f34dd8753d794952d0235df0a1d2b415d55ef60c393c5a197281bfc8a5bdf681a00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa076094ead9021f5472bb12b03aeb521e09d71029dfa5dac90afa7cb44cbdfc5bd80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a0579a97aa89dbeb98396792baa31c4a7ea8e2f41da084140f07bb4bd655b72dd5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2244b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be32244d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32244e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc12a448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2a44a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62a44d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32a44e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc130083805") .to_vec(), + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212d91e0ad5060ad206f9034fa04c83b66c9d766a11c5302ddf195e489be135a96d289a447b8f472cb38487d658a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208a78402625a00808466a22a2cb90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb8608ff2f806af499b5704af0c43fd553e955d27ae7622090f38f4c8b3438f55341051badb02abb1c8ed74d18b5bed72de25127d60e3b4d0ca99b22354b8bca2357fafcb0755eb0d61e97fc7575a5ba27de548cd0017e8177df9c3f4db36e4db39b5f8488208a5a010b36eeee610eb8fd862ea3fd1a9fef0b60829ec6a8a9217f757f4595b9799968208a6a04c83b66c9d766a11c5302ddf195e489be135a96d289a447b8f472cb38487d658808db6c72c9f2d8eae719dd920ce14aad7c968fa58d14199554914bc1ee873a5c30d6bf530adcfc1bafe3d19248c9f4a0bdb728b309e6bab205749f1d0c4c0730c00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa01c0c14576d895ac5ee059ca87003dd354b0135ef20381f0864e3635212473bdea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208a88402625a00808466a22a2fb90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb8608eb82ca384a2783e7b3eac15e62cede677ed7ffe7b65192682862888f53a41bd9e9668c67f8183dfe3492c4fe5ca706616262c999610710a5ddd126223edd5aca5dd88731df16503796931a56aabb1a747c23302f44fa504766bab674f756fbef8488208a6a04c83b66c9d766a11c5302ddf195e489be135a96d289a447b8f472cb38487d6588208a7a01c0c14576d895ac5ee059ca87003dd354b0135ef20381f0864e3635212473bde80282132396ca0067e53784fa76f1e54a5062d709d986ad67b3fc1af55c36e19cd5f34d00fbc8e28bd6efe75afd696f7476cd59dcef7f85e7d7e8d64441af3aa2c01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa07f472cd0045d5751fb839285cd34d38944031d12ca79f5cdb95fc803fe314780a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208a98402625a00808466a22a32b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb8608bdab2df74f889d68d125ea0bb536413fab26e9e251a0b44c8b4097943ae811ce9384fdad4e6f81880717fa57d31bac715ee8e18e39d5204b332ee90d384ccb92b593bcff2256a2f013623e2c69ef8e8e04218de33b33ef1a725731e2a25ab49f8488208a7a01c0c14576d895ac5ee059ca87003dd354b0135ef20381f0864e3635212473bde8208a8a07f472cd0045d5751fb839285cd34d38944031d12ca79f5cdb95fc803fe31478080521712094a69465ab786abee685ba960e6dc814b3a9ddd7168ddf3a8b209f57720f23cf2e5cd2b3ff2f01887cad5b3fa63dce7f937bbabef5ebe8339aca3f3f300a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a0000000000000000000000000000000000000000000000000000000000000000012031098111a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0273c6048b21e7d25636156a707b0be6ba081bcf7381f9b5019580f5aa70369e2a0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a033ff9ba3990e4af75e9e1a6beb627bfc13f4bb7a788fb8ce61c8e90abacfcc5080a0ad34ceb1c793eb6ab9036cecf8c0a1239b9edba58f94890173098a17d9b7693ba0f34dd8753d794952d0235df0a1d2b415d55ef60c393c5a197281bfc8a5bdf681a00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa076094ead9021f5472bb12b03aeb521e09d71029dfa5dac90afa7cb44cbdfc5bd80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a0579a97aa89dbeb98396792baa31c4a7ea8e2f41da084140f07bb4bd655b72dd5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2244b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be32244d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32244e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc12a448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2a44a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62a44d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32a44e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc130083805").to_vec() + ], + //2214 + vec![ + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ae9080ae608f90463a0c13597cb89679cf0b6f2ba3e0ae0781e5ec72c8f839c11083d6704d765137011a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca00bf9dee767e66678856f4c62a62515f54a39ebd7cb57ccb04ed25a22eff7065ba03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208988402625a008229a88466a229ffb90223d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2f048fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ffb2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be3d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b3e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc108f8ae0fb860a41bc57efe7ace714408c524070ad0e41bd17cb44f1367c23d64507edd2f94a804b86ad9f326e5fd7ff2646a77811d4013be08d719f6f24a81bf8ffae796c2c8238c79574ae05967517a1d194d27ae6f410c991e06d6431b490cc1826a9faa51f848820896a031f2ac651e45ab653e7a49287e7ca9754bea2e8e8dc87ea8062a6d43e4c9033f820897a0c13597cb89679cf0b6f2ba3e0ae0781e5ec72c8f839c11083d6704d765137011807a5af307aee11ef5106ca8d8a1a8596e48dc2ffcc3d0797e6ad57cbe8da519a8224042fdabede179427ba5021fa621d46b0cb8fcf285ee78cb0ba18dc7e325e701a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0ac8875032a5bec1f6b3d2e91c9f082e6a8ecbd326126a1a3bc6ecb14c3a4c1d0a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208998402625a00808466a22a02b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860ad4541e9b8a1c3d0def1a3f2d6d353c1d18f8c3d84822e29b413d5fa1fb77ee303add7c1441f7ac6a60e13f0b649483b105859b56e224feb6133a246fa60338e146d5747265994759964d4101d57914d4f3f00c380ff9b91dcb676851917880ff848820897a0c13597cb89679cf0b6f2ba3e0ae0781e5ec72c8f839c11083d6704d765137011820898a0ac8875032a5bec1f6b3d2e91c9f082e6a8ecbd326126a1a3bc6ecb14c3a4c1d0800e69a592db1d57d38c94298eff1ba8209e2a4b7b45b0c05b4d23c894b1c3d9285d446ee4d885a42a33b101c4ac7307f70b8173d5c89a67bafe8795ac3203449200a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0b1d096fbb6737a689f80e8e2f48811add6d9d6ec5cc631cb04a9a8dae0a562b4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000282089a8402625a00808466a22a05b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860a1f04d66e852eae33aeaf6a2b1a08b223f61e8a765894f9cdfbc6ac8aa0c04314df54fd0b98e14d2081c66fc5c49e162086853717104f1b5296adbba0b75643b00587131a47060e9e588ae216887576f41b6ea2e586615116bb46f6c40be812bf848820898a0ac8875032a5bec1f6b3d2e91c9f082e6a8ecbd326126a1a3bc6ecb14c3a4c1d0820899a0b1d096fbb6737a689f80e8e2f48811add6d9d6ec5cc631cb04a9a8dae0a562b480c2efdccaf70cac8ec2926f52473dd4c3b23004bbde1cb1f61ddcfa06deae348d3aa81b0237708debe61dadf589e79d9520f2011e8f8812cdfd1a60af3f4d8b6e01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310d00f1a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0273c6048b21e7d25636156a707b0be6ba081bcf7381f9b5019580f5aa70369e2a0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a033ff9ba3990e4af75e9e1a6beb627bfc13f4bb7a788fb8ce61c8e90abacfcc5080a0ad34ceb1c793eb6ab9036cecf8c0a1239b9edba58f94890173098a17d9b7693ba0f34dd8753d794952d0235df0a1d2b415d55ef60c393c5a197281bfc8a5bdf681a00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa076094ead9021f5472bb12b03aeb521e09d71029dfa5dac90afa7cb44cbdfc5bd80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a0579a97aa89dbeb98396792baa31c4a7ea8e2f41da084140f07bb4bd655b72dd5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2244b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be32244d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32244e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc12a448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2a44a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62a44d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32a44e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc130083805") .to_vec(), + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212d91e0ad5060ad206f9034fa010b36eeee610eb8fd862ea3fd1a9fef0b60829ec6a8a9217f757f4595b979996a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208a68402625a00808466a22a29b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860a679406d91eb9bc53857d50bfc12077371071b1473cfe4ede4016745fbdaf827a42ba7771b88e76e48b5ed027d9ef4f3126386b84dfd011f66506ea063b6b9f6e961e8d4cac5beafa34b5692b0aa45c80bfef8abe5ecb1be81434b55caa26a09f8488208a4a0860594f9818bfca1851dfd23d0a567e39ba5fc4631dac97a4d2d1f99d0420d0b8208a5a010b36eeee610eb8fd862ea3fd1a9fef0b60829ec6a8a9217f757f4595b97999680d54103bebc9a230cc3f1034869ea17dadc3af3be04031eacceff13864e33ec927514d121e198968d2cf5776aac920f3b771a762662b56a387f0844f6a426172000a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa04c83b66c9d766a11c5302ddf195e489be135a96d289a447b8f472cb38487d658a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208a78402625a00808466a22a2cb90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb8608ff2f806af499b5704af0c43fd553e955d27ae7622090f38f4c8b3438f55341051badb02abb1c8ed74d18b5bed72de25127d60e3b4d0ca99b22354b8bca2357fafcb0755eb0d61e97fc7575a5ba27de548cd0017e8177df9c3f4db36e4db39b5f8488208a5a010b36eeee610eb8fd862ea3fd1a9fef0b60829ec6a8a9217f757f4595b9799968208a6a04c83b66c9d766a11c5302ddf195e489be135a96d289a447b8f472cb38487d658808db6c72c9f2d8eae719dd920ce14aad7c968fa58d14199554914bc1ee873a5c30d6bf530adcfc1bafe3d19248c9f4a0bdb728b309e6bab205749f1d0c4c0730c00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa01c0c14576d895ac5ee059ca87003dd354b0135ef20381f0864e3635212473bdea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208a88402625a00808466a22a2fb90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb8608eb82ca384a2783e7b3eac15e62cede677ed7ffe7b65192682862888f53a41bd9e9668c67f8183dfe3492c4fe5ca706616262c999610710a5ddd126223edd5aca5dd88731df16503796931a56aabb1a747c23302f44fa504766bab674f756fbef8488208a6a04c83b66c9d766a11c5302ddf195e489be135a96d289a447b8f472cb38487d6588208a7a01c0c14576d895ac5ee059ca87003dd354b0135ef20381f0864e3635212473bde80282132396ca0067e53784fa76f1e54a5062d709d986ad67b3fc1af55c36e19cd5f34d00fbc8e28bd6efe75afd696f7476cd59dcef7f85e7d7e8d64441af3aa2c01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a0000000000000000000000000000000000000000000000000000000000000000012031098111a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0273c6048b21e7d25636156a707b0be6ba081bcf7381f9b5019580f5aa70369e2a0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a033ff9ba3990e4af75e9e1a6beb627bfc13f4bb7a788fb8ce61c8e90abacfcc5080a0ad34ceb1c793eb6ab9036cecf8c0a1239b9edba58f94890173098a17d9b7693ba0f34dd8753d794952d0235df0a1d2b415d55ef60c393c5a197281bfc8a5bdf681a00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa076094ead9021f5472bb12b03aeb521e09d71029dfa5dac90afa7cb44cbdfc5bd80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a0579a97aa89dbeb98396792baa31c4a7ea8e2f41da084140f07bb4bd655b72dd5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2244b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be32244d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32244e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc12a448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2a44a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62a44d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32a44e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc130083805").to_vec() + ], + //2216 + vec![ + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ae9080ae608f90463a0c13597cb89679cf0b6f2ba3e0ae0781e5ec72c8f839c11083d6704d765137011a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca00bf9dee767e66678856f4c62a62515f54a39ebd7cb57ccb04ed25a22eff7065ba03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208988402625a008229a88466a229ffb90223d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2f048fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ffb2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be3d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b3e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc108f8ae0fb860a41bc57efe7ace714408c524070ad0e41bd17cb44f1367c23d64507edd2f94a804b86ad9f326e5fd7ff2646a77811d4013be08d719f6f24a81bf8ffae796c2c8238c79574ae05967517a1d194d27ae6f410c991e06d6431b490cc1826a9faa51f848820896a031f2ac651e45ab653e7a49287e7ca9754bea2e8e8dc87ea8062a6d43e4c9033f820897a0c13597cb89679cf0b6f2ba3e0ae0781e5ec72c8f839c11083d6704d765137011807a5af307aee11ef5106ca8d8a1a8596e48dc2ffcc3d0797e6ad57cbe8da519a8224042fdabede179427ba5021fa621d46b0cb8fcf285ee78cb0ba18dc7e325e701a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0ac8875032a5bec1f6b3d2e91c9f082e6a8ecbd326126a1a3bc6ecb14c3a4c1d0a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208998402625a00808466a22a02b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860ad4541e9b8a1c3d0def1a3f2d6d353c1d18f8c3d84822e29b413d5fa1fb77ee303add7c1441f7ac6a60e13f0b649483b105859b56e224feb6133a246fa60338e146d5747265994759964d4101d57914d4f3f00c380ff9b91dcb676851917880ff848820897a0c13597cb89679cf0b6f2ba3e0ae0781e5ec72c8f839c11083d6704d765137011820898a0ac8875032a5bec1f6b3d2e91c9f082e6a8ecbd326126a1a3bc6ecb14c3a4c1d0800e69a592db1d57d38c94298eff1ba8209e2a4b7b45b0c05b4d23c894b1c3d9285d446ee4d885a42a33b101c4ac7307f70b8173d5c89a67bafe8795ac3203449200a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0b1d096fbb6737a689f80e8e2f48811add6d9d6ec5cc631cb04a9a8dae0a562b4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948fdaaa7e6631e438625ca25c857a3727ea28e565a02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000282089a8402625a00808466a22a05b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb860a1f04d66e852eae33aeaf6a2b1a08b223f61e8a765894f9cdfbc6ac8aa0c04314df54fd0b98e14d2081c66fc5c49e162086853717104f1b5296adbba0b75643b00587131a47060e9e588ae216887576f41b6ea2e586615116bb46f6c40be812bf848820898a0ac8875032a5bec1f6b3d2e91c9f082e6a8ecbd326126a1a3bc6ecb14c3a4c1d0820899a0b1d096fbb6737a689f80e8e2f48811add6d9d6ec5cc631cb04a9a8dae0a562b480c2efdccaf70cac8ec2926f52473dd4c3b23004bbde1cb1f61ddcfa06deae348d3aa81b0237708debe61dadf589e79d9520f2011e8f8812cdfd1a60af3f4d8b6e01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310d00f1a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0273c6048b21e7d25636156a707b0be6ba081bcf7381f9b5019580f5aa70369e2a0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a033ff9ba3990e4af75e9e1a6beb627bfc13f4bb7a788fb8ce61c8e90abacfcc5080a0ad34ceb1c793eb6ab9036cecf8c0a1239b9edba58f94890173098a17d9b7693ba0f34dd8753d794952d0235df0a1d2b415d55ef60c393c5a197281bfc8a5bdf681a00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa076094ead9021f5472bb12b03aeb521e09d71029dfa5dac90afa7cb44cbdfc5bd80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a0579a97aa89dbeb98396792baa31c4a7ea8e2f41da084140f07bb4bd655b72dd5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2244b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be32244d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32244e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc12a448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2a44a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62a44d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32a44e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc130083805") .to_vec(), + hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212d91e0ad5060ad206f9034fa01c0c14576d895ac5ee059ca87003dd354b0135ef20381f0864e3635212473bdea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208a88402625a00808466a22a2fb90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb8608eb82ca384a2783e7b3eac15e62cede677ed7ffe7b65192682862888f53a41bd9e9668c67f8183dfe3492c4fe5ca706616262c999610710a5ddd126223edd5aca5dd88731df16503796931a56aabb1a747c23302f44fa504766bab674f756fbef8488208a6a04c83b66c9d766a11c5302ddf195e489be135a96d289a447b8f472cb38487d6588208a7a01c0c14576d895ac5ee059ca87003dd354b0135ef20381f0864e3635212473bde80282132396ca0067e53784fa76f1e54a5062d709d986ad67b3fc1af55c36e19cd5f34d00fbc8e28bd6efe75afd696f7476cd59dcef7f85e7d7e8d64441af3aa2c01a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa07f472cd0045d5751fb839285cd34d38944031d12ca79f5cdb95fc803fe314780a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208a98402625a00808466a22a32b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb8608bdab2df74f889d68d125ea0bb536413fab26e9e251a0b44c8b4097943ae811ce9384fdad4e6f81880717fa57d31bac715ee8e18e39d5204b332ee90d384ccb92b593bcff2256a2f013623e2c69ef8e8e04218de33b33ef1a725731e2a25ab49f8488208a7a01c0c14576d895ac5ee059ca87003dd354b0135ef20381f0864e3635212473bde8208a8a07f472cd0045d5751fb839285cd34d38944031d12ca79f5cdb95fc803fe31478080521712094a69465ab786abee685ba960e6dc814b3a9ddd7168ddf3a8b209f57720f23cf2e5cd2b3ff2f01887cad5b3fa63dce7f937bbabef5ebe8339aca3f3f300a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0208333d00c93f838c88a8774b75d999cd8f21f93a4389154a9ff169649c1fd04a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2e42bc54d19116d2348ac83461e2e0915d508ada02c7aa1d61f17c0020c7ed842efa5d227285f8399e151111a12ba247772d0c8eca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028208aa8402625a00808466a22a35b90111d98301040c846765746889676f312e32312e3132856c696e75780000e0299c2ff8ae0fb8608fed9056be3ee0ee5ad5535eb48716ee25b94fdf9cd27b1a113833e99eb0bcf5cb5ae0e4b7d981c19e051e0a54fed48605bd2abaf4b015cf97b7d5d52009ba6cdc8e5fd3bd1db9d5e9b4e2ba79eb51dfd1e630ea47d6d32e12cc038a96615c25f8488208a8a07f472cd0045d5751fb839285cd34d38944031d12ca79f5cdb95fc803fe3147808208a9a0208333d00c93f838c88a8774b75d999cd8f21f93a4389154a9ff169649c1fd0480368b6310d8c27fa2ead40a3e06977f4caa64bd6386db3c84ac5aec106c3d06b6155cc690eb7c12f3f9c5166393d216c208c98f4c25f7184bc215a58e2a0c226300a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a0000000000000000000000000000000000000000000000000000000000000000012031098111a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea0273c6048b21e7d25636156a707b0be6ba081bcf7381f9b5019580f5aa70369e2a0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a033ff9ba3990e4af75e9e1a6beb627bfc13f4bb7a788fb8ce61c8e90abacfcc5080a0ad34ceb1c793eb6ab9036cecf8c0a1239b9edba58f94890173098a17d9b7693ba0f34dd8753d794952d0235df0a1d2b415d55ef60c393c5a197281bfc8a5bdf681a00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa076094ead9021f5472bb12b03aeb521e09d71029dfa5dac90afa7cb44cbdfc5bd80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a0579a97aa89dbeb98396792baa31c4a7ea8e2f41da084140f07bb4bd655b72dd5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2244b2e42bc54d19116d2348ac83461e2e0915d508adaf6af61cafa835c72fe6e9feb717dd4ddf95424e29b6384bd27c0d6c9c616d15cf7fdf0f2f9fc1a4fa9197251b196be32244d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32244e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc12a448fdaaa7e6631e438625ca25c857a3727ea28e565a8c9cbefc0c78b71cdf18eeb8206601e665778faa6b4dd23740f8dd8eeb0c7bcc8f49a1c900396aee02d1639ab7897ff2a44a7876ea32e7a748c697d01345145485561305b24b3f0af694696c1b453b1174a1ea8c1135c247eb168864c9731254bc2f28077f99fe195b477ee699d79f40468aa30c2b62a44d9a13701eafb76870cb220843b8c6476824bfa15b822666ed599d40aa3bc13feb3ca5d5bc9d3ebe23d3460078c755a5ddbd85a0a58a217860fb0ea675b708a82b288f4b32a44e04db2de85453e0936b441c339a26d10cfa71b50996157a84dd67ec797a9ea61e4023c01d5bb28cce995c4c8329900b7b96e5402c02696f6f7b62972af4ee81f3f58afc130083805").to_vec() + ], + ] + } +} diff --git a/light-client/src/fixture/mod.rs b/light-client/src/fixture/mod.rs new file mode 100644 index 0000000..733b6a3 --- /dev/null +++ b/light-client/src/fixture/mod.rs @@ -0,0 +1,68 @@ +use crate::fixture::localnet::Localnet; +use crate::header::eth_header::ETHHeader; +use crate::header::eth_headers::ETHHeaders; +use crate::misc::{Address, ChainId, Hash, Validators}; +use alloc::boxed::Box; +use alloc::vec::Vec; + +use parlia_ibc_proto::ibc::lightclients::parlia::v1::EthHeader; + +pub mod localnet; + +pub trait Network { + fn network(&self) -> ChainId; + fn previous_epoch_header(&self) -> ETHHeader; + fn epoch_header_rlp(&self) -> Vec; + fn epoch_header(&self) -> ETHHeader { + decode_header(self.epoch_header_rlp()) + } + fn epoch_header_plus_1_rlp(&self) -> Vec; + fn epoch_header_plus_1(&self) -> ETHHeader { + decode_header(self.epoch_header_plus_1_rlp()) + } + fn epoch_header_plus_2(&self) -> ETHHeader; + fn epoch_header_plus_3(&self) -> ETHHeader; + fn headers_before_checkpoint(&self) -> ETHHeaders; + fn headers_across_checkpoint(&self) -> ETHHeaders; + fn headers_after_checkpoint(&self) -> ETHHeaders; + fn previous_validators(&self) -> Validators { + self.previous_epoch_header() + .epoch + .unwrap() + .validators() + .clone() + } + fn ibc_store_address(&self) -> Address; + fn success_update_client_non_epoch_input(&self) -> UpdateClientNonEpochInput; + fn success_update_client_epoch_input(&self) -> UpdateClientEpochInput; + fn success_update_client_continuous_input(&self) -> Vec>>; + fn error_update_client_non_neighboring_epoch_input(&self) -> Vec; +} + +pub struct UpdateClientNonEpochInput { + pub header: Vec, + pub trusted_height: u64, + pub trusted_current_validators_hash: Hash, + pub trusted_previous_validators_hash: Hash, + pub expected_storage_root: Hash, +} + +pub struct UpdateClientEpochInput { + pub header: Vec, + pub trusted_height: u64, + pub trusted_current_validators_hash: Hash, + pub trusted_previous_validators_hash: Hash, + pub new_current_validators_hash: Hash, + pub new_previous_validators_hash: Hash, + pub expected_storage_root: Hash, +} + +pub fn localnet() -> Box { + Box::new(Localnet) +} + +pub fn decode_header(rlp_header: Vec) -> ETHHeader { + EthHeader { header: rlp_header }.try_into().unwrap() +} + +// TODO Modify testnet / mainnet after each HF released diff --git a/light-client/src/header/epoch.rs b/light-client/src/header/epoch.rs new file mode 100644 index 0000000..0402f06 --- /dev/null +++ b/light-client/src/header/epoch.rs @@ -0,0 +1,298 @@ +use crate::errors::Error; +use crate::header::validator_set::ValidatorSet; +use crate::misc::{ceil_div, Hash, Validators}; +use patricia_merkle_trie::keccak::keccak_256; + +#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct Epoch { + validator_set: ValidatorSet, + turn_length: u8, + hash: Hash, +} + +impl Epoch { + pub fn new(validator_set: ValidatorSet, turn_length: u8) -> Self { + let seed = [[turn_length].as_slice(), validator_set.hash.as_slice()].concat(); + Self { + validator_set, + turn_length, + hash: keccak_256(&seed), + } + } + pub fn checkpoint(&self) -> u64 { + self.validator_set.checkpoint(self.turn_length) + } + + pub fn hash(&self) -> Hash { + self.hash + } + + pub fn validators(&self) -> &Validators { + &self.validator_set.validators + } + + pub fn turn_length(&self) -> u8 { + self.turn_length + } +} + +#[derive(Clone, Debug, PartialEq)] +pub struct TrustedEpoch<'a> { + inner: &'a Epoch, +} + +impl<'a> TrustedEpoch<'a> { + pub fn validators(&self) -> &Validators { + self.inner.validators() + } + + pub fn checkpoint(&self) -> u64 { + self.inner.checkpoint() + } + + pub fn epoch(&self) -> &'a Epoch { + self.inner + } + + pub fn new(inner: &'a Epoch) -> Self { + Self { inner } + } +} + +#[derive(Clone, Debug, PartialEq)] +pub struct UntrustedEpoch<'a> { + inner: &'a Epoch, +} + +impl<'a> UntrustedEpoch<'a> { + pub fn new(inner: &'a Epoch) -> Self { + Self { inner } + } + pub fn checkpoint(&self) -> u64 { + self.inner.checkpoint() + } + pub fn try_borrow(&'a self, trusted_epoch: &TrustedEpoch) -> Result<&'a Epoch, Error> { + let (result, found, required) = self.contains(trusted_epoch); + if result { + return Ok(self.inner); + } + Err(Error::InsufficientTrustedValidatorsInUntrustedValidators( + self.inner.hash, + found, + required, + )) + } + + fn contains(&self, trusted_epoch: &TrustedEpoch) -> (bool, usize, usize) { + let trusted_validators = trusted_epoch.validators(); + let mut trusted_validator_count = 0; + for x1 in self.inner.validators() { + if trusted_validators.contains(x1) { + trusted_validator_count += 1; + } + } + let required = ceil_div(trusted_validators.len(), 3); + ( + trusted_validator_count >= required, + trusted_validator_count, + required, + ) + } +} + +#[derive(Clone, Debug, PartialEq)] +pub enum EitherEpoch<'a> { + Trusted(TrustedEpoch<'a>), + Untrusted(UntrustedEpoch<'a>), +} + +impl<'a> EitherEpoch<'a> { + pub fn checkpoint(&self) -> u64 { + match self { + EitherEpoch::Trusted(v) => v.checkpoint(), + EitherEpoch::Untrusted(v) => v.checkpoint(), + } + } +} + +#[cfg(test)] +mod test { + use crate::errors::Error; + use crate::header::epoch::{Epoch, TrustedEpoch, UntrustedEpoch, ValidatorSet}; + + #[test] + pub fn test_untrusted_epoch_try_borrow() { + let mut _assert_trusted = |x, y, c_val_borrowable| { + let trusted_validators: ValidatorSet = vec![ + vec![1], + vec![2], + vec![3], + vec![4], + vec![5], + vec![6], + vec![7], + ] + .into(); + let trusted_epoch = Epoch::new(trusted_validators, 1); + let trusted_epoch = TrustedEpoch::new(&trusted_epoch); + let untrusted_epoch = Epoch::new( + ValidatorSet { + validators: x, + hash: [0; 32], + }, + 1, + ); + let untrusted_epoch = UntrustedEpoch::new(&untrusted_epoch); + let (result, count, required) = untrusted_epoch.contains(&trusted_epoch); + assert_eq!(result, c_val_borrowable); + assert_eq!(count, y); + assert_eq!(required, 3); + match untrusted_epoch.try_borrow(&trusted_epoch) { + Ok(borrowed) => { + if c_val_borrowable { + assert_eq!(borrowed, untrusted_epoch.inner); + } else { + unreachable!("unexpected borrowed") + } + } + Err(e) => { + if c_val_borrowable { + unreachable!("unexpected error {:?}", e); + } else { + match e { + Error::InsufficientTrustedValidatorsInUntrustedValidators(_, _, _) => {} + e => unreachable!("unexpected error type {:?}", e), + } + } + } + } + }; + + let assert_trusted = |x, y| _assert_trusted(x, y, true); + assert_trusted( + vec![ + vec![1], + vec![2], + vec![3], + vec![4], + vec![5], + vec![6], + vec![7], + ], + 7, + ); + assert_trusted( + vec![ + vec![1], + vec![2], + vec![3], + vec![4], + vec![15], + vec![16], + vec![17], + ], + 4, + ); + assert_trusted( + vec![ + vec![11], + vec![12], + vec![13], + vec![4], + vec![5], + vec![6], + vec![7], + ], + 4, + ); + assert_trusted( + vec![ + vec![1], + vec![12], + vec![3], + vec![14], + vec![5], + vec![16], + vec![7], + ], + 4, + ); + assert_trusted(vec![vec![1], vec![2], vec![3], vec![4]], 4); + assert_trusted( + vec![ + vec![1], + vec![2], + vec![3], + vec![14], + vec![15], + vec![16], + vec![17], + ], + 3, + ); + assert_trusted( + vec![ + vec![11], + vec![12], + vec![13], + vec![14], + vec![5], + vec![6], + vec![7], + ], + 3, + ); + assert_trusted( + vec![ + vec![1], + vec![12], + vec![3], + vec![14], + vec![5], + vec![16], + vec![17], + ], + 3, + ); + assert_trusted(vec![vec![1], vec![2], vec![3]], 3); + + let assert_untrusted = |x, y| _assert_trusted(x, y, false); + assert_untrusted( + vec![ + vec![1], + vec![2], + vec![13], + vec![14], + vec![15], + vec![16], + vec![17], + ], + 2, + ); + assert_untrusted( + vec![ + vec![11], + vec![12], + vec![13], + vec![14], + vec![15], + vec![6], + vec![7], + ], + 2, + ); + assert_untrusted( + vec![ + vec![1], + vec![12], + vec![3], + vec![14], + vec![15], + vec![16], + vec![17], + ], + 2, + ); + assert_untrusted(vec![vec![1], vec![2]], 2); + } +} diff --git a/light-client/src/header/eth_header.rs b/light-client/src/header/eth_header.rs index 750d257..39f4a19 100644 --- a/light-client/src/header/eth_header.rs +++ b/light-client/src/header/eth_header.rs @@ -10,7 +10,7 @@ use rlp::{Rlp, RlpStream}; use parlia_ibc_proto::ibc::lightclients::parlia::v1::EthHeader as RawETHHeader; use crate::errors::Error; -use crate::header::validator_set::ValidatorSet; +use crate::header::epoch::Epoch; use crate::header::vote_attestation::VoteAttestation; use crate::misc::{Address, BlockNumber, ChainId, Hash, RlpIterator, Validators}; @@ -27,13 +27,14 @@ const BLS_PUBKEY_LENGTH: usize = 48; const VALIDATOR_BYTES_LENGTH: usize = VALIDATOR_BYTES_LENGTH_BEFORE_LUBAN + BLS_PUBKEY_LENGTH; const VALIDATOR_NUM_SIZE: usize = 1; +const TURN_LENGTH_SIZE: usize = 1; + const PARAMS_GAS_LIMIT_BOUND_DIVISOR: u64 = 256; const EMPTY_UNCLE_HASH: Hash = hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"); const EMPTY_NONCE: [u8; 8] = hex!("0000000000000000"); -const EMPTY_MIX_HASH: Hash = - hex!("0000000000000000000000000000000000000000000000000000000000000000"); +const EMPTY_HASH: Hash = hex!("0000000000000000000000000000000000000000000000000000000000000000"); #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] pub struct ETHHeader { @@ -52,9 +53,15 @@ pub struct ETHHeader { pub extra_data: Vec, pub mix_digest: Vec, pub nonce: Vec, + pub base_fee_per_gas: Option, + pub withdrawals_hash: Option>, + pub blob_gas_used: Option, + pub excess_blob_gas: Option, + pub parent_beacon_root: Option>, // calculated by RawETHHeader pub hash: Hash, + pub epoch: Option, } impl ETHHeader { @@ -88,7 +95,8 @@ impl ETHHeader { /// This returns the hash of a block prior to it being sealed. fn seal_hash(&self, chain_id: &ChainId) -> Result { - let mut stream = RlpStream::new_list(16); + let mut stream = RlpStream::new(); + stream.begin_unbounded_list(); stream.append(&chain_id.id()); stream.append(&self.parent_hash); stream.append(&self.uncle_hash); @@ -105,6 +113,32 @@ impl ETHHeader { stream.append(&self.extra_data[..self.extra_data.len() - EXTRA_SEAL].to_vec()); stream.append(&self.mix_digest); stream.append(&self.nonce); + if let Some(parent_beacon_root) = &self.parent_beacon_root { + if parent_beacon_root == &EMPTY_HASH { + if let Some(value) = &self.base_fee_per_gas { + stream.append(value); + } else { + stream.append_empty_data(); + } + if let Some(value) = &self.withdrawals_hash { + stream.append(value); + } else { + stream.append_empty_data(); + } + if let Some(value) = &self.blob_gas_used { + stream.append(value); + } else { + stream.append_empty_data(); + } + if let Some(value) = &self.excess_blob_gas { + stream.append(value); + } else { + stream.append_empty_data(); + } + stream.append(parent_beacon_root); + } + } + stream.finalize_unbounded_list(); Ok(keccak_256(stream.out().as_ref())) } @@ -161,7 +195,7 @@ impl ETHHeader { /// https://github.com/bnb-chain/bsc/blob/7a19cd27b61b342d24a1584efc7fa00de4a5b4f5/consensus/parlia/parlia.go#L755 pub fn verify_seal( &self, - validator_set: &Validators, + validating_epoch: &Epoch, chain_id: &ChainId, ) -> Result { // Resolve the authorization key and check against validators @@ -171,7 +205,7 @@ impl ETHHeader { } let mut valid_signer = false; - for validator in validator_set.iter() { + for validator in validating_epoch.validators().iter() { if validator[0..VALIDATOR_BYTES_LENGTH_BEFORE_LUBAN] == signer { valid_signer = true; break; @@ -181,11 +215,33 @@ impl ETHHeader { return Err(Error::MissingSignerInValidator(self.number, signer)); } - // Don't check that the difficulty corresponds to the turn-ness of the signer + // Ensure that the difficulty corresponds to the turn-ness of the signer + self.verify_validator_rotation(validating_epoch)?; Ok(signer) } + fn verify_validator_rotation(&self, epoch: &Epoch) -> Result<(), Error> { + let offset = (self.number / epoch.turn_length() as u64) as usize % epoch.validators().len(); + let inturn_validator = &epoch.validators()[offset][0..VALIDATOR_BYTES_LENGTH_BEFORE_LUBAN]; + if inturn_validator == self.coinbase { + if self.difficulty != DIFFICULTY_INTURN { + return Err(Error::UnexpectedDifficultyInTurn( + self.number, + self.difficulty, + offset, + )); + } + } else if self.difficulty != DIFFICULTY_NOTURN { + return Err(Error::UnexpectedDifficultyNoTurn( + self.number, + self.difficulty, + offset, + )); + } + Ok(()) + } + pub fn verify_target_attestation(&self, parent: ÐHeader) -> Result { let target_vote_attestation = self.get_vote_attestation()?; let target_data = &target_vote_attestation.data; @@ -236,7 +292,10 @@ impl ETHHeader { { return Err(Error::UnexpectedVoteLength(self.extra_data.len())); } - let start = EXTRA_VANITY + VALIDATOR_NUM_SIZE + (num * VALIDATOR_BYTES_LENGTH); + let start = EXTRA_VANITY + + VALIDATOR_NUM_SIZE + + (num * VALIDATOR_BYTES_LENGTH) + + TURN_LENGTH_SIZE; let end = self.extra_data.len() - EXTRA_SEAL; &self.extra_data[start..end] }; @@ -244,37 +303,37 @@ impl ETHHeader { Rlp::new(attestation_bytes).try_into() } - // https://github.com/bnb-chain/bsc/blob/33e6f840d25edb95385d23d284846955327b0fcd/consensus/parlia/parlia.go#L342 - pub fn get_validator_bytes(&self) -> Option { - if self.extra_data.len() <= EXTRA_VANITY + EXTRA_SEAL { - return None; - } - let num = self.extra_data[EXTRA_VANITY] as usize; - if num == 0 - || self.extra_data.len() <= EXTRA_VANITY + EXTRA_SEAL + num * VALIDATOR_BYTES_LENGTH - { - return None; - } - let start = EXTRA_VANITY + VALIDATOR_NUM_SIZE; - let end = start + num * VALIDATOR_BYTES_LENGTH; - Some( - self.extra_data[start..end] - .chunks(VALIDATOR_BYTES_LENGTH) - .map(|s| s.into()) - .collect(), - ) + pub fn is_epoch(&self) -> bool { + self.number % BLOCKS_PER_EPOCH == 0 } +} - pub fn get_validator_set(&self) -> Result { - Ok(self - .get_validator_bytes() - .ok_or_else(|| Error::MissingValidatorInEpochBlock(self.number))? - .into()) +pub fn get_validator_bytes_and_tern_term(extra_data: &[u8]) -> Result<(Validators, u8), Error> { + if extra_data.len() <= EXTRA_VANITY + EXTRA_SEAL { + return Err(Error::UnexpectedExtraDataLength(extra_data.len())); + } + let num = extra_data[EXTRA_VANITY] as usize; + if num == 0 || extra_data.len() <= EXTRA_VANITY + EXTRA_SEAL + num * VALIDATOR_BYTES_LENGTH { + return Err(Error::UnexpectedExtraDataLength(extra_data.len())); } + let start = EXTRA_VANITY + VALIDATOR_NUM_SIZE; + let end = start + num * VALIDATOR_BYTES_LENGTH; + let turn_length = extra_data[end]; + validate_turn_length(turn_length)?; + Ok(( + extra_data[start..end] + .chunks(VALIDATOR_BYTES_LENGTH) + .map(|s| s.into()) + .collect(), + turn_length, + )) +} - pub fn is_epoch(&self) -> bool { - self.number % BLOCKS_PER_EPOCH == 0 +pub fn validate_turn_length(turn_length: u8) -> Result<(), Error> { + if !(turn_length == 1 || (3..=9).contains(&turn_length)) { + return Err(Error::UnexpectedTurnLength(turn_length)); } + Ok(()) } impl TryFrom for ETHHeader { @@ -306,6 +365,7 @@ impl TryFrom for ETHHeader { let withdrawals_hash: Option> = rlp.try_next_as_val().map(Some).unwrap_or(None); let blob_gas_used: Option = rlp.try_next_as_val().map(Some).unwrap_or(None); let excess_blob_gas: Option = rlp.try_next_as_val().map(Some).unwrap_or(None); + let parent_beacon_root: Option> = rlp.try_next_as_val().map(Some).unwrap_or(None); // Check that the extra-data contains the vanity, validators and signature let extra_size = extra_data.len(); @@ -325,7 +385,7 @@ impl TryFrom for ETHHeader { } // Ensure that the mix digest is zero as we don't have fork protection currently - if mix_digest != EMPTY_MIX_HASH { + if mix_digest != EMPTY_HASH { return Err(Error::UnexpectedMixHash(number)); } // Ensure that the block doesn't contain any uncles which are meaningless in PoA @@ -361,11 +421,12 @@ impl TryFrom for ETHHeader { stream.append(&extra_data); stream.append(&mix_digest); stream.append(&nonce); - // https://github.com/bnb-chain/bsc/blob/4b45c5993c87d12c520a89e0d3d059e4d6b6eb9c/core/types/gen_header_rlp.go#L57 + if base_fee_per_gas.is_some() || withdrawals_hash.is_some() || blob_gas_used.is_some() || excess_blob_gas.is_some() + || parent_beacon_root.is_some() { if let Some(v) = base_fee_per_gas { stream.append(&v); @@ -373,31 +434,49 @@ impl TryFrom for ETHHeader { stream.append_empty_data(); } } - if withdrawals_hash.is_some() || blob_gas_used.is_some() || excess_blob_gas.is_some() { - if let Some(v) = withdrawals_hash { - stream.append(&v); + if withdrawals_hash.is_some() + || blob_gas_used.is_some() + || excess_blob_gas.is_some() + || parent_beacon_root.is_some() + { + if let Some(v) = &withdrawals_hash { + stream.append(v); } else { stream.append_empty_data(); } } - if blob_gas_used.is_some() || excess_blob_gas.is_some() { + if blob_gas_used.is_some() || excess_blob_gas.is_some() || parent_beacon_root.is_some() { if let Some(v) = blob_gas_used { stream.append(&v); } else { stream.append_empty_data(); } } - if excess_blob_gas.is_some() { + if excess_blob_gas.is_some() || parent_beacon_root.is_some() { if let Some(v) = excess_blob_gas { stream.append(&v); } else { stream.append_empty_data(); } } + if parent_beacon_root.is_some() { + if let Some(v) = &parent_beacon_root { + stream.append(v); + } else { + stream.append_empty_data(); + } + } stream.finalize_unbounded_list(); let buffer_vec: Vec = stream.out().to_vec(); let hash: Hash = keccak_256(&buffer_vec); + let epoch = if number % BLOCKS_PER_EPOCH == 0 { + let (validators, turn_length) = get_validator_bytes_and_tern_term(&extra_data)?; + Some(Epoch::new(validators.into(), turn_length)) + } else { + None + }; + Ok(Self { parent_hash, uncle_hash, @@ -414,7 +493,13 @@ impl TryFrom for ETHHeader { extra_data, mix_digest, nonce, + base_fee_per_gas, + excess_blob_gas, + withdrawals_hash, + blob_gas_used, + parent_beacon_root, hash, + epoch, }) } } @@ -423,46 +508,48 @@ impl TryFrom for ETHHeader { pub(crate) mod test { use crate::errors::Error; use crate::header::eth_header::{ - ETHHeader, EXTRA_SEAL, EXTRA_VANITY, PARAMS_GAS_LIMIT_BOUND_DIVISOR, + ETHHeader, DIFFICULTY_INTURN, DIFFICULTY_NOTURN, EXTRA_SEAL, EXTRA_VANITY, + PARAMS_GAS_LIMIT_BOUND_DIVISOR, VALIDATOR_BYTES_LENGTH_BEFORE_LUBAN, }; - use hex_literal::hex; use rlp::RlpStream; + use rstest::*; - use crate::header::testdata::*; + use crate::fixture::{localnet, Network}; + use crate::header::epoch::Epoch; + use alloc::boxed::Box; use parlia_ibc_proto::ibc::lightclients::parlia::v1::EthHeader as RawETHHeader; - impl TryFrom<ÐHeader> for RawETHHeader { - type Error = Error; - - fn try_from(header: ÐHeader) -> Result { - let mut stream = RlpStream::new_list(15); - stream.append(&header.parent_hash); - stream.append(&header.uncle_hash); - stream.append(&header.coinbase); - stream.append(&header.root.to_vec()); - stream.append(&header.tx_hash); - stream.append(&header.receipt_hash); - stream.append(&header.bloom); - stream.append(&header.difficulty); - stream.append(&header.number); - stream.append(&header.gas_limit); - stream.append(&header.gas_used); - stream.append(&header.timestamp); - stream.append(&header.extra_data); - stream.append(&header.mix_digest); - stream.append(&header.nonce); - Ok(RawETHHeader { - header: stream.out().to_vec(), - }) + fn to_raw(header: ÐHeader) -> RawETHHeader { + let mut stream = RlpStream::new(); + stream.begin_unbounded_list(); + stream.append(&header.parent_hash); + stream.append(&header.uncle_hash); + stream.append(&header.coinbase); + stream.append(&header.root.to_vec()); + stream.append(&header.tx_hash); + stream.append(&header.receipt_hash); + stream.append(&header.bloom); + stream.append(&header.difficulty); + stream.append(&header.number); + stream.append(&header.gas_limit); + stream.append(&header.gas_used); + stream.append(&header.timestamp); + stream.append(&header.extra_data); + stream.append(&header.mix_digest); + stream.append(&header.nonce); + stream.finalize_unbounded_list(); + RawETHHeader { + header: stream.out().to_vec(), } } - #[test] - fn test_error_try_from_missing_vanity() { - let mut header = header_31297201(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_try_from_missing_vanity(#[case] hp: Box) { + let mut header = hp.epoch_header_plus_1(); header.extra_data = [0u8; EXTRA_VANITY - 1].to_vec(); - let raw = RawETHHeader::try_from(&header).unwrap(); + let raw = to_raw(&header); let err = ETHHeader::try_from(raw).unwrap_err(); match err { Error::MissingVanityInExtraData(number, actual, min) => { @@ -474,11 +561,12 @@ pub(crate) mod test { }; } - #[test] - fn test_error_try_from_missing_signature() { - let mut header = header_31297201(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_try_from_missing_signature(#[case] hp: Box) { + let mut header = hp.epoch_header_plus_1(); header.extra_data = [0u8; EXTRA_VANITY + EXTRA_SEAL - 1].to_vec(); - let raw = RawETHHeader::try_from(&header).unwrap(); + let raw = to_raw(&header); let err = ETHHeader::try_from(raw).unwrap_err(); match err { Error::MissingSignatureInExtraData(number, actual, min) => { @@ -490,11 +578,12 @@ pub(crate) mod test { }; } - #[test] - fn test_error_try_from_unexpected_mix_hash() { - let mut header = header_31297201(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_try_from_unexpected_mix_hash(#[case] hp: Box) { + let mut header = hp.epoch_header_plus_1(); header.mix_digest = vec![]; - let raw = RawETHHeader::try_from(&header).unwrap(); + let raw = to_raw(&header); let err = ETHHeader::try_from(raw).unwrap_err(); match err { Error::UnexpectedMixHash(number) => { @@ -504,11 +593,12 @@ pub(crate) mod test { }; } - #[test] - fn test_error_try_from_unexpected_uncle_hash() { - let mut header = header_31297201(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_try_from_unexpected_uncle_hash(#[case] hp: Box) { + let mut header = hp.epoch_header_plus_1(); header.uncle_hash = vec![]; - let raw = RawETHHeader::try_from(&header).unwrap(); + let raw = to_raw(&header); let err = ETHHeader::try_from(raw).unwrap_err(); match err { Error::UnexpectedUncleHash(number) => { @@ -518,11 +608,12 @@ pub(crate) mod test { }; } - #[test] - fn test_error_try_from_unexpected_difficulty() { - let mut header = header_31297201(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_try_from_unexpected_difficulty(#[case] hp: Box) { + let mut header = hp.epoch_header_plus_1(); header.difficulty = 10; - let raw = RawETHHeader::try_from(&header).unwrap(); + let raw = to_raw(&header); let err = ETHHeader::try_from(raw).unwrap_err(); match err { Error::UnexpectedDifficulty(number, actual) => { @@ -533,11 +624,12 @@ pub(crate) mod test { }; } - #[test] - fn test_error_try_from_unexpected_nonce() { - let mut header = header_31297201(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_try_from_unexpected_nonce(#[case] hp: Box) { + let mut header = hp.epoch_header_plus_1(); header.nonce = vec![]; - let raw = RawETHHeader::try_from(&header).unwrap(); + let raw = to_raw(&header); let err = ETHHeader::try_from(raw).unwrap_err(); match err { Error::UnexpectedNonce(number) => { @@ -547,159 +639,30 @@ pub(crate) mod test { }; } - #[test] - fn test_success_try_from_with_bep336_field() { - let base_fn = || { - let header = header_31297200(); - let mut stream = RlpStream::new(); - stream.begin_unbounded_list(); - stream.append(&header.parent_hash); - stream.append(&header.uncle_hash); - stream.append(&header.coinbase); - stream.append(&header.root.to_vec()); - stream.append(&header.tx_hash); - stream.append(&header.receipt_hash); - stream.append(&header.bloom); - stream.append(&header.difficulty); - stream.append(&header.number); - stream.append(&header.gas_limit); - stream.append(&header.gas_used); - stream.append(&header.timestamp); - stream.append(&header.extra_data); - stream.append(&header.mix_digest); - stream.append(&header.nonce); - stream - }; - - let mut stream = base_fn(); - stream.finalize_unbounded_list(); - let raw = RawETHHeader { - header: stream.out().to_vec(), - }; - let v = ETHHeader::try_from(raw).unwrap(); - assert_eq!(v.hash, header_31297200().hash); - - // with base_fee_per_gas - let base_fee_per_gas: u64 = 2; - let mut stream = base_fn(); - stream.append(&base_fee_per_gas); - stream.finalize_unbounded_list(); - let raw = RawETHHeader { - header: stream.out().to_vec(), - }; - ETHHeader::try_from(raw).unwrap(); - - // with withdrawals_hash - let withdrawals_hash = header_31297200().tx_hash; - let mut stream = base_fn(); - stream.append(&base_fee_per_gas); - stream.append(&withdrawals_hash); - stream.finalize_unbounded_list(); - let raw = RawETHHeader { - header: stream.out().to_vec(), - }; - ETHHeader::try_from(raw).unwrap(); - - // with blob_gas_used - let blob_gas_used: u64 = 3; - let mut stream = base_fn(); - stream.append(&base_fee_per_gas); - stream.append(&withdrawals_hash); - stream.append(&blob_gas_used); - stream.finalize_unbounded_list(); - let raw = RawETHHeader { - header: stream.out().to_vec(), - }; - ETHHeader::try_from(raw).unwrap(); - - // with excess_blob_gas - let excess_blob_gas: u64 = 4; - let mut stream = base_fn(); - stream.append(&base_fee_per_gas); - stream.append(&withdrawals_hash); - stream.append(&blob_gas_used); - stream.append(&excess_blob_gas); - stream.finalize_unbounded_list(); - let raw = RawETHHeader { - header: stream.out().to_vec(), - }; - ETHHeader::try_from(raw).unwrap(); - - // testnet after Tycho - let mut stream = RlpStream::new(); - stream.begin_unbounded_list(); - stream.append( - &hex!("bc7d1149db8ecb83b784b9418511e9997e12a0acf419ca344b952da42b25209a").to_vec(), - ); - stream.append( - &hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").to_vec(), - ); - stream.append(&hex!("53387f3321fd69d1e030bb921230dfb188826aff").to_vec()); - stream.append( - &hex!("6b295725152189db64d8afe76ebbc78d04ad3452ee5c0613d2cdde234aae6518").to_vec(), - ); - stream.append( - &hex!("b49a9e69547c01e22100afa0dac47ad573a73c8a456d368aa78a20a1be3b8f61").to_vec(), - ); - stream.append( - &hex!("3f1e435e6e4833d5ce8ff9fbdb1e8fc61b71c75f03de98e1dd96662363230fb4").to_vec(), - ); - stream.append(&hex!("000020000000080100900040a00001000000400000020000000440002020081000001002000000000000000000000001020000040004100000111001000c60000240000100020008020100880000000020100000040400000000010000000000002c0020220200000006000028000800082200000000088000002010100008000040400482000000080080001000000008100400280000000040008000000020000080004000062008000010020000000000000000000020000080080000002080021012040028040002000002000000400000000408064000104002000060001200000010000000010040340000110020008040000420004000080000000000").to_vec()); - stream.append(&u64::from_str_radix("1", 16).unwrap()); - stream.append(&u64::from_str_radix("25b7469", 16).unwrap()); - stream.append(&u64::from_str_radix("42c1d80", 16).unwrap()); - stream.append(&u64::from_str_radix("14c285", 16).unwrap()); - stream.append(&u64::from_str_radix("661fc104", 16).unwrap()); - stream.append(&hex!("d883010405846765746888676f312e32312e36856c696e7578000000821df8b9f8b381f7b860881105fa9e628179b4be7c807d56d7f83e0354604a31a3a0610dc2cfd312f089cca6cf0dc22e0a675179cafcdd0fcd5309257163c6c53b48404671f1cbdb5d4c38de16ffc0e0951c4d3141de1748399ddf4fa51b4fadfbe0201b4d30a2b7fffef84c84025b7467a0dd8f3ec7f7613d048271569ed3b3712b1a8c91a9039ab0e15395b345a76459fa84025b7468a0bc7d1149db8ecb83b784b9418511e9997e12a0acf419ca344b952da42b25209a80174ffd16859a8984cb5c4420784ac48f5df3c5be2225f009d3f78a26ab8766fa05589316bb3d657c8b5f0796afcef09bb284c4bbef83d89d980fe6958022906e01").to_vec()); - stream.append( - &hex!("0000000000000000000000000000000000000000000000000000000000000000").to_vec(), - ); - stream.append(&hex!("0000000000000000").to_vec()); - stream.append(&u64::from_str_radix("0", 16).unwrap()); - stream.append( - &hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").to_vec(), - ); - stream.append(&u64::from_str_radix("0", 16).unwrap()); - stream.append(&u64::from_str_radix("0", 16).unwrap()); - stream.finalize_unbounded_list(); - let raw = RawETHHeader { - header: stream.out().to_vec(), - }; - let hash = ETHHeader::try_from(raw).unwrap().hash; - assert_eq!( - hash, - hex!("6de91bc2b08a30d2082b7d3077e6ad381d040373b706d231cff899b096322972") - ) - } - - #[test] - fn test_success_verify_seal() { - let validators = validators_in_31297000(); + #[rstest] + #[case::localnet(localnet())] + fn test_success_verify_seal(#[case] hp: Box) { + let prev_epoch = hp.previous_epoch_header().epoch.unwrap(); let blocks = vec![ - header_31297199(), - header_31297200(), - header_31297201(), - header_31297202(), + hp.epoch_header(), + hp.epoch_header_plus_1(), + hp.epoch_header_plus_2(), ]; for block in blocks { - if let Err(e) = block.verify_seal(&validators, &mainnet()) { + if let Err(e) = block.verify_seal(&prev_epoch, &hp.network()) { unreachable!("{} {:?}", block.number, e); } } } - #[test] - fn test_error_verify_seal() { - let validators = validators_in_31297000(); - let mut blocks = vec![ - header_31297199(), - header_31297200(), - header_31297201(), - header_31297202(), - ]; + #[rstest] + #[case::localnet(localnet())] + fn test_error_verify_seal(#[case] hp: Box) { + let prev_epoch = hp.previous_epoch_header().epoch.unwrap(); + let mut blocks = vec![hp.epoch_header_plus_1(), hp.epoch_header_plus_2()]; for block in blocks.iter_mut() { - let result = block.verify_seal(&validators[0..1].to_vec(), &mainnet()); + let result = block.verify_seal(&Epoch::new(vec![].into(), 1), &hp.network()); match result.unwrap_err() { Error::MissingSignerInValidator(number, address) => { assert_eq!(block.number, number); @@ -711,7 +674,7 @@ pub(crate) mod test { for mut block in blocks.iter_mut() { block.coinbase = vec![]; - let result = block.verify_seal(&validators, &mainnet()); + let result = block.verify_seal(&prev_epoch, &hp.network()); match result.unwrap_err() { Error::UnexpectedCoinbase(number) => assert_eq!(block.number, number), e => unreachable!("{:?}", e), @@ -719,13 +682,13 @@ pub(crate) mod test { } } - #[test] - fn test_success_verify_cascading_fields() { + #[rstest] + #[case::localnet(localnet())] + fn test_success_verify_cascading_fields(#[case] hp: Box) { let blocks = vec![ - header_31297199(), - header_31297200(), - header_31297201(), - header_31297202(), + hp.epoch_header(), + hp.epoch_header_plus_1(), + hp.epoch_header_plus_2(), ]; for (i, block) in blocks.iter().enumerate() { if i == 0 { @@ -737,10 +700,11 @@ pub(crate) mod test { } } - #[test] - fn test_error_verify_cascading_fields() { - let parent = header_31297199(); - let mut block = header_31297200(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_verify_cascading_fields(#[case] hp: Box) { + let parent = hp.epoch_header(); + let mut block = hp.epoch_header_plus_1(); block.gas_limit = 10000; block.gas_used = parent.gas_limit + 1; let result = block.verify_cascading_fields(&parent); @@ -753,8 +717,8 @@ pub(crate) mod test { err => unreachable!("{:?}", err), } - let parent = header_31297199(); - let block = header_31297201(); + let parent = hp.epoch_header(); + let block = hp.epoch_header_plus_2(); let result = block.verify_cascading_fields(&parent); match result.unwrap_err() { Error::UnexpectedHeaderRelation( @@ -775,8 +739,8 @@ pub(crate) mod test { err => unreachable!("{:?}", err), } - let parent = header_31297199(); - let mut block = header_31297200(); + let parent = hp.epoch_header(); + let mut block = hp.epoch_header_plus_1(); block.gas_used = 0; block.gas_limit = 0; let result = block.verify_cascading_fields(&parent); @@ -784,19 +748,19 @@ pub(crate) mod test { Error::UnexpectedGasDiff(number, diff, limit) => { assert_eq!(block.number, number); assert_eq!(parent.gas_limit / PARAMS_GAS_LIMIT_BOUND_DIVISOR, limit); - assert_eq!(140000000, diff); + assert_eq!(parent.gas_limit - block.gas_limit, diff); } err => unreachable!("{:?}", err), } } - #[test] - fn test_success_verify_vote_attestation() { + #[rstest] + #[case::localnet(localnet())] + fn test_success_verify_vote_attestation(#[case] hp: Box) { let blocks = vec![ - header_31297199(), - header_31297200(), - header_31297201(), - header_31297202(), + hp.epoch_header(), + hp.epoch_header_plus_1(), + hp.epoch_header_plus_2(), ]; for (i, block) in blocks.iter().enumerate() { if i == 0 { @@ -808,10 +772,11 @@ pub(crate) mod test { } } - #[test] - fn test_error_verify_vote_attestation() { - let header = header_31297201(); - let parent = header_31297201(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_verify_vote_attestation(#[case] hp: Box) { + let header = hp.epoch_header_plus_1(); + let parent = hp.epoch_header_plus_1(); let err = header.verify_vote_attestation(&parent).unwrap_err(); match err { Error::UnexpectedTargetVoteAttestationRelation( @@ -826,10 +791,10 @@ pub(crate) mod test { err => unreachable!("{:?}", err), } - let mut block = header_31297200(); + let mut block = hp.epoch_header_plus_1(); block.extra_data = vec![]; let err = block - .verify_vote_attestation(&header_31297199()) + .verify_vote_attestation(&hp.epoch_header()) .unwrap_err(); match err { Error::UnexpectedVoteLength(size) => { @@ -838,8 +803,8 @@ pub(crate) mod test { err => unreachable!("{:?}", err), } - let header = header_31297202(); - let mut parent = header_31297201(); + let header = hp.epoch_header_plus_2(); + let mut parent = hp.epoch_header_plus_1(); parent.extra_data = header.extra_data.clone(); let err = header.verify_vote_attestation(&parent).unwrap_err(); match err { @@ -855,4 +820,43 @@ pub(crate) mod test { err => unreachable!("{:?}", err), } } + + #[rstest] + #[case::localnet(localnet())] + fn test_error_verify_validator_rotation_inturn(#[case] hp: Box) { + let mut header = hp.epoch_header(); + header.difficulty = DIFFICULTY_NOTURN; + let prev = hp.previous_epoch_header(); + match header + .verify_validator_rotation(&prev.epoch.unwrap()) + .unwrap_err() + { + Error::UnexpectedDifficultyInTurn(e1, e2, _e3) => { + assert_eq!(e1, header.number); + assert_eq!(e2, header.difficulty); + } + err => unreachable!("{:?}", err), + } + } + + #[rstest] + #[case::localnet(localnet())] + fn test_error_verify_validator_rotation_noturn(#[case] hp: Box) { + let mut header = hp.epoch_header(); + header.difficulty = DIFFICULTY_INTURN; + let prev = hp.previous_epoch_header(); + header.coinbase = prev.epoch.clone().unwrap().validators()[1] + [0..VALIDATOR_BYTES_LENGTH_BEFORE_LUBAN] + .to_vec(); + match header + .verify_validator_rotation(&prev.epoch.unwrap()) + .unwrap_err() + { + Error::UnexpectedDifficultyNoTurn(e1, e2, _e3) => { + assert_eq!(e1, header.number); + assert_eq!(e2, header.difficulty); + } + err => unreachable!("{:?}", err), + } + } } diff --git a/light-client/src/header/eth_headers.rs b/light-client/src/header/eth_headers.rs index 8dab3de..c25cf3d 100644 --- a/light-client/src/header/eth_headers.rs +++ b/light-client/src/header/eth_headers.rs @@ -3,12 +3,11 @@ use alloc::vec::Vec; use parlia_ibc_proto::ibc::lightclients::parlia::v1::EthHeader; use crate::errors::Error; -use crate::header::validator_set::EitherValidatorSet::{Trusted, Untrusted}; -use crate::header::validator_set::{ - EitherValidatorSet, TrustedValidatorSet, UntrustedValidatorSet, -}; +use crate::errors::Error::MissingEpochInfoInEpochBlock; +use crate::header::epoch::EitherEpoch::{Trusted, Untrusted}; +use crate::header::epoch::{EitherEpoch, Epoch, TrustedEpoch, UntrustedEpoch}; -use crate::misc::{BlockNumber, ChainId, Validators}; +use crate::misc::{BlockNumber, ChainId}; use super::eth_header::ETHHeader; use super::BLOCKS_PER_EPOCH; @@ -20,76 +19,36 @@ pub struct ETHHeaders { } impl ETHHeaders { - pub fn verify_non_neighboring_epoch( - &self, - chain_id: &ChainId, - checkpoint: u64, - trusted_validators: TrustedValidatorSet, - next_validators: UntrustedValidatorSet, - ) -> Result<(), Error> { - let n_val = next_validators.try_borrow(&trusted_validators)?; - - // Ensure all the headers are successfully chained. - self.verify_cascading_fields()?; - - // Ensure valid seals - let hs: Vec = self - .all - .iter() - .filter(|h| h.number >= checkpoint) - .cloned() - .collect(); - for h in hs.iter() { - h.verify_seal(n_val, chain_id)?; - } - - let hs = ETHHeaders { - target: self.target.clone(), - all: hs, - }; - - // Ensure target is finalized - let (child, grand_child) = hs.verify_finalized()?; - - // Ensure BLS signature is collect - // At the just checkpoint BLS signature uses previous validator set. - for h in &[child, grand_child] { - let vote = h.get_vote_attestation()?; - vote.verify(h.number, n_val)?; - } - Ok(()) - } - pub fn verify( &self, chain_id: &ChainId, - current_validators: &EitherValidatorSet, - previous_validators: &TrustedValidatorSet, + current_epoch: &EitherEpoch, + previous_epoch: &TrustedEpoch, ) -> Result<(), Error> { // Ensure the header after the next or next checkpoint must not exist. let epoch = self.target.number / BLOCKS_PER_EPOCH; - let checkpoint = epoch * BLOCKS_PER_EPOCH + previous_validators.checkpoint(); - let next_checkpoint = (epoch + 1) * BLOCKS_PER_EPOCH + current_validators.checkpoint(); + let checkpoint = epoch * BLOCKS_PER_EPOCH + previous_epoch.checkpoint(); + let next_checkpoint = (epoch + 1) * BLOCKS_PER_EPOCH + current_epoch.checkpoint(); let (c_val, n_val) = self.verify_header_size( epoch, checkpoint, next_checkpoint, - previous_validators, - current_validators, + previous_epoch, + current_epoch, )?; // Ensure all the headers are successfully chained. self.verify_cascading_fields()?; // Ensure valid seals - let p_val = previous_validators.validators(); + let p_val = previous_epoch.validators(); for h in self.all.iter() { if h.number >= next_checkpoint { h.verify_seal(unwrap_n_val(h.number, &n_val)?, chain_id)?; } else if h.number >= checkpoint { h.verify_seal(unwrap_c_val(h.number, &c_val)?, chain_id)?; } else { - h.verify_seal(p_val, chain_id)?; + h.verify_seal(previous_epoch.epoch(), chain_id)?; } } @@ -101,9 +60,9 @@ impl ETHHeaders { for h in &[child, grand_child] { let vote = h.get_vote_attestation()?; if h.number > next_checkpoint { - vote.verify(h.number, unwrap_n_val(h.number, &n_val)?)?; + vote.verify(h.number, unwrap_n_val(h.number, &n_val)?.validators())?; } else if h.number > checkpoint { - vote.verify(h.number, unwrap_c_val(h.number, &c_val)?)?; + vote.verify(h.number, unwrap_c_val(h.number, &c_val)?.validators())?; } else { vote.verify(h.number, p_val)?; } @@ -153,18 +112,18 @@ impl ETHHeaders { )) } - fn verify_header_size<'a>( - &self, + fn verify_header_size<'a, 'b>( + &'b self, epoch: u64, checkpoint: u64, next_checkpoint: u64, - previous_validators: &TrustedValidatorSet, - current_validators: &'a EitherValidatorSet, - ) -> Result<(Option<&'a Validators>, Option), Error> { + previous_epoch: &TrustedEpoch, + current_epoch: &'a EitherEpoch, + ) -> Result<(Option<&'a Epoch>, Option<&'b Epoch>), Error> { let hs: Vec<ÐHeader> = self.all.iter().filter(|h| h.number >= checkpoint).collect(); - match current_validators { + match current_epoch { // ex) t=200 then 200 <= h < 411 (c_val(200) can be borrowed by p_val) - Untrusted(untrusted_c_val) => { + Untrusted(untrusted) => { // Ensure headers are before the next_checkpoint if hs.iter().any(|h| h.number >= next_checkpoint) { return Err(Error::UnexpectedNextCheckpointHeader( @@ -177,27 +136,30 @@ impl ETHHeaders { if hs.is_empty() { Ok((None, None)) } else { - Ok((Some(untrusted_c_val.try_borrow(previous_validators)?), None)) + Ok((Some(untrusted.try_borrow(previous_epoch)?), None)) } } // ex) t=201 then 201 <= h < 611 (n_val(400) can be borrowed by c_val(200)) - Trusted(c_val) => { - // Get n_val if epoch after checkpoint ex) 400 - let n_val = match hs.iter().find(|h| h.is_epoch()) { - Some(h) => h.get_validator_set()?, - None => return Ok((Some(c_val.validators()), None)), + Trusted(trusted) => { + // Get next_epoch if epoch after checkpoint ex) 400 + let next_epoch = match hs.iter().find(|h| h.is_epoch()) { + Some(h) => h + .epoch + .as_ref() + .ok_or_else(|| MissingEpochInfoInEpochBlock(h.number))?, + None => return Ok((Some(trusted.epoch()), None)), }; // Finish if no headers over next checkpoint were found let hs: Vec<&ÐHeader> = hs.iter().filter(|h| h.number >= next_checkpoint).collect(); if hs.is_empty() { - return Ok((Some(c_val.validators()), None)); + return Ok((Some(trusted.epoch()), None)); } // Ensure n_val(400) can be borrowed by c_val(200) - let next_next_checkpoint = (epoch + 2) * BLOCKS_PER_EPOCH + n_val.checkpoint(); - UntrustedValidatorSet::new(&n_val).try_borrow(c_val)?; + let next_next_checkpoint = (epoch + 2) * BLOCKS_PER_EPOCH + next_epoch.checkpoint(); + UntrustedEpoch::new(next_epoch).try_borrow(trusted)?; // Ensure headers are before the next_next_checkpoint if hs.iter().any(|h| h.number >= next_next_checkpoint) { @@ -206,7 +168,7 @@ impl ETHHeaders { next_next_checkpoint, )); } - Ok((Some(c_val.validators()), Some(n_val.validators))) + Ok((Some(trusted.epoch()), Some(next_epoch))) } } } @@ -256,101 +218,95 @@ fn verify_finalized( Ok(()) } -fn unwrap_n_val(n: BlockNumber, n_val: &Option) -> Result<&Validators, Error> { - n_val - .as_ref() - .ok_or_else(|| Error::MissingNextValidatorSet(n)) +fn unwrap_n_val<'a>(n: BlockNumber, n_val: &'a Option<&'a Epoch>) -> Result<&'a Epoch, Error> { + n_val.ok_or_else(|| Error::MissingNextValidatorSet(n)) } -fn unwrap_c_val<'a>( - n: BlockNumber, - c_val: &'a Option<&'a Validators>, -) -> Result<&'a Validators, Error> { +fn unwrap_c_val<'a>(n: BlockNumber, c_val: &'a Option<&'a Epoch>) -> Result<&'a Epoch, Error> { c_val.ok_or_else(|| Error::MissingCurrentValidatorSet(n)) } #[cfg(test)] mod test { use crate::errors::Error; + use crate::header::constant::BLOCKS_PER_EPOCH; - use crate::header::eth_header::ETHHeader; + use crate::header::eth_header::{get_validator_bytes_and_tern_term, ETHHeader}; use crate::header::eth_headers::ETHHeaders; - use crate::header::testdata::*; - use crate::header::validator_set::{ - EitherValidatorSet, TrustedValidatorSet, UntrustedValidatorSet, ValidatorSet, - }; + + use crate::fixture::*; + use crate::header::epoch::{EitherEpoch, Epoch, TrustedEpoch, UntrustedEpoch}; use crate::header::Header; use crate::misc::Validators; use hex_literal::hex; use light_client::types::Any; - use std::prelude::rust_2015::Vec; + use rstest::rstest; + use std::prelude::rust_2015::{Box, Vec}; use std::vec; - fn trust(v: &ValidatorSet) -> TrustedValidatorSet { - TrustedValidatorSet::new(v) + fn trust(v: &Epoch) -> TrustedEpoch { + TrustedEpoch::new(v) } - fn untrust(v: &ValidatorSet) -> UntrustedValidatorSet { - UntrustedValidatorSet::new(v) + fn untrust(v: &Epoch) -> UntrustedEpoch { + UntrustedEpoch::new(v) } - fn empty() -> ValidatorSet { + fn empty() -> Epoch { let validators: Validators = vec![]; - validators.into() + Epoch::new(validators.into(), 1) } - #[test] - fn test_success_verify_before_checkpoint() { - let headers = create_before_checkpoint_headers(); - let p_val = validators_in_31297000().into(); + #[rstest] + #[case::localnet(localnet())] + fn test_success_verify_before_checkpoint(#[case] hp: Box) { + let headers = hp.headers_before_checkpoint(); + let p_val = hp.previous_epoch_header().epoch.unwrap(); let p_val = trust(&p_val); let c_val = empty(); - let c_val = EitherValidatorSet::Trusted(trust(&c_val)); - headers.verify(&mainnet(), &c_val, &p_val).unwrap(); - - // from epoch - let headers: ETHHeaders = - vec![header_31297200(), header_31297201(), header_31297202()].into(); - let c_val = empty(); - let c_val = EitherValidatorSet::Untrusted(untrust(&c_val)); - headers.verify(&mainnet(), &c_val, &p_val).unwrap(); + let c_val = EitherEpoch::Untrusted(untrust(&c_val)); + headers.verify(&hp.network(), &c_val, &p_val).unwrap(); } - #[test] - fn test_success_verify_across_checkpoint() { - let headers = create_across_checkpoint_headers(); - let p_val = validators_in_31297000().into(); + #[rstest] + #[case::localnet(localnet())] + fn test_success_verify_across_checkpoint(#[case] hp: Box) { + let headers = hp.headers_across_checkpoint(); + let p_val = hp.previous_epoch_header().epoch.unwrap(); let p_val = trust(&p_val); - let c_val = header_31297200().get_validator_bytes().unwrap().into(); - let c_val = EitherValidatorSet::Trusted(trust(&c_val)); - headers.verify(&mainnet(), &c_val, &p_val).unwrap(); + let c_val = hp.epoch_header().epoch.unwrap(); + let c_val = EitherEpoch::Trusted(trust(&c_val)); + headers.verify(&hp.network(), &c_val, &p_val).unwrap(); } - #[test] - fn test_success_verify_after_checkpoint() { - let headers = create_after_checkpoint_headers(); + #[rstest] + #[case::localnet(localnet())] + fn test_success_verify_after_checkpoint(#[case] hp: Box) { + let headers = hp.headers_after_checkpoint(); let p_val = empty(); let p_val = trust(&p_val); - let c_val = header_31297200().get_validator_bytes().unwrap().into(); - let c_val = EitherValidatorSet::Trusted(trust(&c_val)); - headers.verify(&mainnet(), &c_val, &p_val).unwrap(); + let c_val = hp.epoch_header().epoch.unwrap(); + let c_val = EitherEpoch::Trusted(trust(&c_val)); + headers.verify(&hp.network(), &c_val, &p_val).unwrap(); } - #[test] - fn test_error_verify_before_checkpoint() { - let header = create_before_checkpoint_headers(); - let mainnet = &mainnet(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_verify_before_checkpoint(#[case] hp: Box) { + let previous_epoch = hp.previous_epoch_header().epoch.unwrap(); + let header = hp.headers_before_checkpoint(); + let network = &hp.network(); // first block uses previous broken validator set - let mut validators = validators_in_31297000(); - for v in validators.iter_mut() { - v.remove(0); + let mut validators = previous_epoch.validators().to_vec(); + for val in validators.iter_mut() { + val[0] = 0; } - let p_val = validators.into(); + let p_val = Epoch::new(validators.into(), previous_epoch.turn_length()); let p_val = trust(&p_val); - let c_val = empty(); - let c_val = EitherValidatorSet::Untrusted(untrust(&c_val)); - let result = header.verify(mainnet, &c_val, &p_val); + let c_val = hp.epoch_header().epoch.unwrap(); + let c_val = EitherEpoch::Trusted(trust(&c_val)); + let result = header.verify(network, &c_val, &p_val); match result.unwrap_err() { Error::MissingSignerInValidator(number, _) => { assert_eq!(number, header.target.number) @@ -359,22 +315,24 @@ mod test { } } - #[test] - fn test_error_verify_across_checkpoint() { - let mut c_val: Validators = header_31297200().get_validator_bytes().unwrap(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_verify_across_checkpoint(#[case] hp: Box) { + let epoch = hp.epoch_header().epoch.unwrap(); + let mut c_val: Validators = epoch.validators().clone(); for (i, v) in c_val.iter_mut().enumerate() { v[0] = i as u8; } - let c_val = c_val.into(); - let c_val = EitherValidatorSet::Trusted(trust(&c_val)); - let p_val = validators_in_31297000().into(); + let c_val = Epoch::new(c_val.into(), 1); + let c_val = EitherEpoch::Trusted(trust(&c_val)); + let p_val = Epoch::new(hp.previous_validators().into(), 1); let p_val = trust(&p_val); - let mainnet = &mainnet(); + let network = &hp.network(); // last block uses new empty validator set - let header = create_across_checkpoint_headers(); - let result = header.verify(mainnet, &c_val, &p_val); + let header = hp.headers_across_checkpoint(); + let result = header.verify(network, &c_val, &p_val); match result.unwrap_err() { Error::MissingSignerInValidator(number, _) => { //25428811 uses next validator @@ -384,15 +342,16 @@ mod test { } } - #[test] - fn test_error_verify_non_continuous_header() { - let mut headers = create_after_checkpoint_headers(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_verify_non_continuous_header(#[case] hp: Box) { + let mut headers = hp.headers_after_checkpoint(); headers.all[1] = headers.all[0].clone(); let p_val = empty(); let p_val = trust(&p_val); - let c_val = header_31297200().get_validator_bytes().unwrap().into(); - let c_val = EitherValidatorSet::Trusted(trust(&c_val)); - let result = headers.verify(&mainnet(), &c_val, &p_val); + let c_val = hp.epoch_header().epoch.unwrap(); + let c_val = EitherEpoch::Trusted(trust(&c_val)); + let result = headers.verify(&hp.network(), &c_val, &p_val); match result.unwrap_err() { Error::UnexpectedHeaderRelation(e1, e2, _, _, _, _) => { assert_eq!(e1, headers.target.number); @@ -402,15 +361,21 @@ mod test { } } - #[test] - fn test_error_verify_too_many_headers_to_finalize() { - let mut headers = create_after_checkpoint_headers(); - headers.all.push(header_31297214()); - let p_val = empty(); - let p_val = trust(&p_val); - let c_val = header_31297200().get_validator_bytes().unwrap().into(); - let c_val = EitherValidatorSet::Trusted(trust(&c_val)); - let result = headers.verify(&mainnet(), &c_val, &p_val); + #[rstest] + #[case::localnet(localnet())] + fn test_error_verify_too_many_headers_to_finalize(#[case] hp: Box) { + let mut headers: ETHHeaders = vec![ + hp.epoch_header(), + hp.epoch_header_plus_1(), + hp.epoch_header_plus_2(), + ] + .into(); + headers.all.push(hp.epoch_header_plus_3()); + let p_val = Epoch::new(hp.previous_validators().into(), 1); + let p_val = TrustedEpoch::new(&p_val); + let c_val = hp.epoch_header().epoch.unwrap(); + let c_val = EitherEpoch::Untrusted(untrust(&c_val)); + let result = headers.verify(&hp.network(), &c_val, &p_val); match result.unwrap_err() { Error::UnexpectedTooManyHeadersToFinalize(e1, e2) => { assert_eq!(e1, headers.target.number, "block error"); @@ -420,15 +385,16 @@ mod test { } } - #[test] - fn test_error_verify_invalid_header_size() { - let mut headers = create_after_checkpoint_headers(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_verify_invalid_header_size(#[case] hp: Box) { + let mut headers = hp.headers_after_checkpoint(); headers.all.pop(); let p_val = empty(); let p_val = trust(&p_val); - let c_val = header_31297200().get_validator_bytes().unwrap().into(); - let c_val = EitherValidatorSet::Trusted(trust(&c_val)); - let result = headers.verify(&mainnet(), &c_val, &p_val); + let c_val = hp.epoch_header().epoch.unwrap(); + let c_val = EitherEpoch::Trusted(trust(&c_val)); + let result = headers.verify(&hp.network(), &c_val, &p_val); match result.unwrap_err() { Error::InvalidVerifyingHeaderLength(e1, e2) => { assert_eq!(e1, headers.target.number, "block error"); @@ -440,7 +406,7 @@ mod test { #[test] fn test_success_verify_finalized_including_not_finalized_block() { - let header= hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212961e0a9e060a9b06f90318a0793f4896c559772686c55bc1140baa291e62ef268061713080c9d02193ecd549a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d1d6bf74282782b0b3eb1413c901d6ecf02e8e28a0c2081e9bb02adf2b65cf9b3f83b71142e4a963584516174fa671c75e3c9b82f0a071f511f91544d703b0a8a74ef6b93df3d261d961b15f5abb688a115a164f59aba0a93cf4b9598e6c8ff24b4aea19f8a64291de129c57118291fee8c4b16de22fe5b90100462586c2f1cfbc9f58faae6f8ff10b2b6a5e6acb0d3077c87e9b05031ab93d1e8f62b32a766618ad9af4b9a1629f42008273c409768e35be70154b2721e87ef585d19504837158efa1b705d99333122ea79c48b387729b7e491f8154d55c5f180e6d01668a76152594e3183ccae8490d8e8e92500e0f5c2ad6b0e415f45ac72f95fab24672835de1c48e0a9f38923ec496ae5dd5fb62043cfd7bc0c8f0c5c3f1670ef7d1d7fc2b907ffe63ced34467b8fbf2300dba03b63a57722ff07ae56961f52d1a32862a09ef3698d1b93bc636286a56b3cadb8b22998372f4c28cd1e72c7ab0f0ab0db8c6aa8105556c1a3481c6fc66ac24d5ae775fba850d343a210feb028401e6aa4184084fe2c684014933a184650a4afbb90118d88301020b846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5831dffffb8609865f38b886fdf9133435031ff4e3af35f0f7dcd165bed2f80f523864cdcaacd102a5d538972060573218a8cbd201d9418fde9d217990d8faf5c5c382618820fe24cf490f1010d92a66114d3d5305e953ef00268448068d5fb4638a94c4269a2f84c8401e6aa3fa0cba1480655a9172eb8fc0a0ea9cd5a285b9fcea8489bde764a134c52a8cc0ff98401e6aa40a0793f4896c559772686c55bc1140baa291e62ef268061713080c9d02193ecd54980a72fc8f10e414df8a61ea1d4d2f3362b2fa0c8c7c444848769e6d67bdbcce4de2683fdae80bcd5a90a8f92d76b7ae426f11d51a7f1d785fefe1cbf451f67186401a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9a060a9706f90314a094904149695c8adb89cd6f020cb278275a2fd4483cfc10d7d3dab8121f69f306a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e9ae3261a475a27bb1028f140bc2a7c843318afda0c2081e9bb02adf2b65cf9b3f83b71142e4a963584516174fa671c75e3c9b82f0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028401e6aa4284085832a78084650a4affb90118d88301020a846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5831dffffb860b02f4314b40616294282cb1f66df8eb23b1c26395b214e78ecd75a9646e0fd008b5f9bae4b24647db4f4b4a92ca0aee4032f3a8917546bfc7c078624ab1b0be6bf87972f4d9815f4f96ad00ba291308ee5c5f6c63243e9518ab6c1f42ce34470f84c8401e6aa40a0793f4896c559772686c55bc1140baa291e62ef268061713080c9d02193ecd5498401e6aa41a094904149695c8adb89cd6f020cb278275a2fd4483cfc10d7d3dab8121f69f30680ec8e7cec4b6c25fa8b22c40e9ecae359c542137ed189c711f5cd7616f4619f331f3eb09268047aaf47af3b83786ee4471c31779848627720f48a7bf5ca50f14601a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800ae6040ae304f90260a0cadbcaaebd901c23537425e903b40a054d6cca192f0f01ecf3d45d9afce4cef3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ea0a6e3c511bbd10f4519ece37dc24887e11b55da054d3ce938c69efbd57808ae22c9030bfa64ebfe6b7f16d5574b1fada5c336d96a0ba3499b3199bc9606a46f865d4abc0cfa9e1be68940ba8a91eb0de4e02d660f5a04278f75943cad9584a22440799ef5f5db6618e33bed532b709b859bb44e0d02fb901006eb746324da2c67a4c1a4a70aeed04073c9d207629cda74bd61604bf345053d797915346c4e531f9033b2df9067732f89d89f3e90b6ae92122c64c020964e7de5facd5784b66c76ac979829d886e8779f9b1f4b5e5efd954c956a916bb1d5f71937998aa33863da5ace9aa48432959190bfee853e57f55beeae4c6b8efcc0ff092f7f1f73afcd1daf3dcbb7c3f82fab45bacbc95366ad9fc6d495e5968e65c346248d49a759b29086e28a57f6af62769dfac85aba6ddf3013783b02ad9d872e8afa60d631a9f0c838298a5955222d611e3d1b79eb8a872beaa37fa5a9a00e50dabd0ca073bc1ff981bf906c0fda18164ae868587e9b802cdf7e26fae9a811f0b028401e6aa438408583b00840105fdbe84650a4b02b861d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a239e14e61ceb442e61edd782ed2e011994aca0236541d845851453ed45e1c950b3672dcc21546bd65e746c468b17a3722b7c529d64d9c3a4b41136ab03e48147e01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9e060a9b06f90318a0cc482c7a97c2c547a7e1483c14e65bb6087ca7257c15ff673f946298c57e7d90a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ee226379db83cffc681495730c11fdde79ba4c0ca0921e5a9881b361b462e86c18d8170303f37f3576c4298f951b164a3a0ffa7950a04a318f22b6185bdebef3900d7c65bcceed28c6906605406b54bd9eb07cb6a266a07a8d59ef980eed078ac8f192425c1fffbf5210a9c92a2065c40639f6421c2367b90100cae58a5a44a877dfab933564fb46b73ec4c3d9c7f068cd492e7b13a3d43cca90ce095bebe264c59a13537dd3575e47c5a87922ba687d73fbdf4cf75c5c7fae998edcc9956b64445fc973aacd815ef67bbc3ce25deb67e19207fff0d98cc0cd558a0ec9eb2bb7bee5b4e736041f80bdcb0862fbf2e9afff5e3ce0959b8fa1cfb795fe04f69cbfecdde7a927c01fe87cc89cad2e277b31e63a5619f6ffac97cb631f4ba69ce7fea3f16e3c2b15fb8b2462cbf6ef9b62b3e77173fb306f19eb12fbe2ecdedfb32acbcf3efa25d9f79838b2b76b25cec051447eab71740e862feb2fd214e4db5568ceb4a791b6bec6c1a972726641bce9fe4f68e46edf15df75e652028401e6aa448408583b00840107e57384650a4b05b90118d88301020a846765746888676f312e32302e34856c696e7578000000b19df4a2f8b5831dffffb860a4cc53efef08386da2bcdf2ccd02f5772899f7e1f3b0252b21bf309dd6f96034ee6570316f1767c75acdd7f6691589051341d1cdf1f118c5c47c505a2e48a47da6e7d26c3107799b8cf767cff1382115896c6b74f0df094690ee36d0fcecf95ef84c8401e6aa41a094904149695c8adb89cd6f020cb278275a2fd4483cfc10d7d3dab8121f69f3068401e6aa43a0cc482c7a97c2c547a7e1483c14e65bb6087ca7257c15ff673f946298c57e7d908093e10e56b7f84c8f756b3bd5422d93053db5f5a55dee436bae6d8066674e131f4f430278fc3cb1f4d9f3dd0c85410694b92887718d431d8ddf25524ece35d03501a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a04eedf58a08358d43f0d37410f1c301efcc3dd738eff0b07bb4f82c83f30a0cc2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ef0274e31810c9df02f98fafde0f841f4e66a1cda04773baafa2984559c063e6b1f50e3019baae941124e89d5d7bc3f009e484a3d0a0c350e76080e62e8e4f45c1d424daec63750b940344655e81f56f0c65f1e7ab40a0cfd21dbf9df8503fb97bcd511aa04483116eb7afd0d4702532d1ff0b8e8b849eb90100002e022444181418d2d2414984070420434880e00f19494c8452044a5a7001298681544650c412916e119ca3241220808c0110050418214674422800002620a06440c08029440f8f296082ac8214002db995a0c59de7580a06168014c01036205a8ca0628e8205000458ea6110210d480a002ce0809e0410430084100d4c6420390a20a40479e91a14982410089018c4902ca40d601091081181105024a110a007904082087e211261d6008c42ceb44942602191022801165326a8aa1f8f28f8e0262c92228732026080028c8812d2057a10b884800048b10c13545b9e20f6340ab485c910af5a940909064e044f41446c6b8581653051e81603b101fc498c0b028401e6aa458408583b008385259f84650a4b08b90118d88301020a846765746888676f312e32302e34856c696e7578000000b19df4a2f8b5831dffffb86088dd96fd990be352a39175463f3902ec9f4f036ed7cd8ab3ce3f4cc70dfc8230a1a1f856e28cbc84a4ed1f95431f63cd0464f1c2f061593bfaf3eae388264d02420af41cfc0e01525f438bc3cf11b9c5a988aa6bb9c82098d567b339709ac676f84c8401e6aa43a0cc482c7a97c2c547a7e1483c14e65bb6087ca7257c15ff673f946298c57e7d908401e6aa44a04eedf58a08358d43f0d37410f1c301efcc3dd738eff0b07bb4f82c83f30a0cc2801962735bca49e800156401aa4bbe2e32d58f36cc22ce3cfd8da23ca72e10eb2f44fa1c1a1840959059d86e6f1b936457795534d45c8a554c3060e9dd39ec108001a00000000000000000000000000000000000000000000000000000000000000000880000000000000000801200221400000000000000000000000000000000000000002a140000000000000000000000000000000000000000").to_vec(); + let header= hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ae9080ae608f90463a0794978ac680964fb5ada43366fa4d33a490c93ec6893304ddee68a59f2cafabaa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a09f0bb93d54df1fcbfd84d4173496de9cff0f403319bbbaf15791ccde774b73d8a03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211308402625a008229a884669fb2e3b90223d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8048fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6ca7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98cb2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833309f8ae0fb860834538868d2c79371ead2f10fc7229fd3b3aaf1d7d8607fd7e1d2efba7df1008c105fdab4ad8029f86cfde1e3aa7dd24194fcf07502bb6c281fc3cbc08ad8cb467de57cbfd1bb93fabe72f77ece8f991a2b7a4d7fb301d54547c6cb4b612d06ff84882112ea042dfe9761fb9a677b088a868f237a171d511bea581f643844a1c98267902391882112fa0794978ac680964fb5ada43366fa4d33a490c93ec6893304ddee68a59f2cafaba80321f35c8454a2691a2efff6894cae6277ea06390978294fe0d10fe03f432fd07440d802ca0858a2d6138230b37d1a9148a3d76fbe8492854e637c9aad7494e3401a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa09696424e13500cdc742b049c6459c0bc4cb357eab5d9fb48a2e79787c8897a1fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211318402625a008084669fb2e6b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860b6de9ffe941751cd11463bbd4bde69d3bc2b79868f669f9e2c4c327f036e6d558b013469a91670607dd88d63dc50b95d00719e118a17e5b72418b6ae4bef7aebbcdaa44b79f8c0677ac32c71312d84db44e6e9216bd84fb97c7d0701a4a03431f84882112fa0794978ac680964fb5ada43366fa4d33a490c93ec6893304ddee68a59f2cafaba821130a09696424e13500cdc742b049c6459c0bc4cb357eab5d9fb48a2e79787c8897a1f80e5619874ecb4463f8d86981d939ddb4d0eaa151c6080c7067788e06699789d0a415e921b8824e8adc7907e5bbccec9373b22c7fe8a48527e9348aa957871b63300a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0e3aa9bc64f82ccd7e70ec415d73263d9da9f3bb44b78bed500033379df9be8aaa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211328402625a008084669fb2e9b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb86095a056c77bdeb59da26e665d69e75cc5667cd43df693a55f20f5f248483a3ce10cdd996b29c7fd6ba3f9e31cb4ac089c0b5bc13e77d83f17096d88f280b8d47ffd8b58b66bd760d0ccd4d26e0c2a7bb3ec168a06a815cfbdde9a2e18c32ac74ef848821130a09696424e13500cdc742b049c6459c0bc4cb357eab5d9fb48a2e79787c8897a1f821131a0e3aa9bc64f82ccd7e70ec415d73263d9da9f3bb44b78bed500033379df9be8aa80c04c6f70fa142c7486f7bed7e29a247f1203d58c7481c9aefef1193e6404112e32486f8d4dc8c7c558ae0b1bf860f6e05d425b7726ba7a4e2dac6e3e3eb83d3d00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310e8201a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea065b83aa9b59125f9b090432f556c6ff947b5708eb11ca5ea26342392860be00aa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a064c0a17f12a753c3fc032723866ac267ad8b7e05e7aa2e75bb680175d936617580a01a41c640130c53b3c90b1b5c691ed467218cee97aade5aac9306e72865851e27a004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0a1575ef06513a19d2a28390e83958d2a3ffe166b530255b0fb5559d33409914d80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a063a8a6161448a60a47ddbafa00899bed224e9f80072b35a1dbc64a82e85cd9b5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2244a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2244b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442244e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f83332a448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2a44b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442a44d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d22a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833330093808").to_vec(); let any: Any = header.try_into().unwrap(); let header = Header::try_from(any).unwrap(); header.headers.verify_finalized().unwrap(); @@ -448,10 +414,10 @@ mod test { #[test] fn test_error_verify_finalized_no_finalized_header() { - let header= hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212961e0a9e060a9b06f90318a0793f4896c559772686c55bc1140baa291e62ef268061713080c9d02193ecd549a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d1d6bf74282782b0b3eb1413c901d6ecf02e8e28a0c2081e9bb02adf2b65cf9b3f83b71142e4a963584516174fa671c75e3c9b82f0a071f511f91544d703b0a8a74ef6b93df3d261d961b15f5abb688a115a164f59aba0a93cf4b9598e6c8ff24b4aea19f8a64291de129c57118291fee8c4b16de22fe5b90100462586c2f1cfbc9f58faae6f8ff10b2b6a5e6acb0d3077c87e9b05031ab93d1e8f62b32a766618ad9af4b9a1629f42008273c409768e35be70154b2721e87ef585d19504837158efa1b705d99333122ea79c48b387729b7e491f8154d55c5f180e6d01668a76152594e3183ccae8490d8e8e92500e0f5c2ad6b0e415f45ac72f95fab24672835de1c48e0a9f38923ec496ae5dd5fb62043cfd7bc0c8f0c5c3f1670ef7d1d7fc2b907ffe63ced34467b8fbf2300dba03b63a57722ff07ae56961f52d1a32862a09ef3698d1b93bc636286a56b3cadb8b22998372f4c28cd1e72c7ab0f0ab0db8c6aa8105556c1a3481c6fc66ac24d5ae775fba850d343a210feb028401e6aa4184084fe2c684014933a184650a4afbb90118d88301020b846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5831dffffb8609865f38b886fdf9133435031ff4e3af35f0f7dcd165bed2f80f523864cdcaacd102a5d538972060573218a8cbd201d9418fde9d217990d8faf5c5c382618820fe24cf490f1010d92a66114d3d5305e953ef00268448068d5fb4638a94c4269a2f84c8401e6aa3fa0cba1480655a9172eb8fc0a0ea9cd5a285b9fcea8489bde764a134c52a8cc0ff98401e6aa40a0793f4896c559772686c55bc1140baa291e62ef268061713080c9d02193ecd54980a72fc8f10e414df8a61ea1d4d2f3362b2fa0c8c7c444848769e6d67bdbcce4de2683fdae80bcd5a90a8f92d76b7ae426f11d51a7f1d785fefe1cbf451f67186401a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9a060a9706f90314a094904149695c8adb89cd6f020cb278275a2fd4483cfc10d7d3dab8121f69f306a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e9ae3261a475a27bb1028f140bc2a7c843318afda0c2081e9bb02adf2b65cf9b3f83b71142e4a963584516174fa671c75e3c9b82f0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028401e6aa4284085832a78084650a4affb90118d88301020a846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5831dffffb860b02f4314b40616294282cb1f66df8eb23b1c26395b214e78ecd75a9646e0fd008b5f9bae4b24647db4f4b4a92ca0aee4032f3a8917546bfc7c078624ab1b0be6bf87972f4d9815f4f96ad00ba291308ee5c5f6c63243e9518ab6c1f42ce34470f84c8401e6aa40a0793f4896c559772686c55bc1140baa291e62ef268061713080c9d02193ecd5498401e6aa41a094904149695c8adb89cd6f020cb278275a2fd4483cfc10d7d3dab8121f69f30680ec8e7cec4b6c25fa8b22c40e9ecae359c542137ed189c711f5cd7616f4619f331f3eb09268047aaf47af3b83786ee4471c31779848627720f48a7bf5ca50f14601a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800ae6040ae304f90260a0cadbcaaebd901c23537425e903b40a054d6cca192f0f01ecf3d45d9afce4cef3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ea0a6e3c511bbd10f4519ece37dc24887e11b55da054d3ce938c69efbd57808ae22c9030bfa64ebfe6b7f16d5574b1fada5c336d96a0ba3499b3199bc9606a46f865d4abc0cfa9e1be68940ba8a91eb0de4e02d660f5a04278f75943cad9584a22440799ef5f5db6618e33bed532b709b859bb44e0d02fb901006eb746324da2c67a4c1a4a70aeed04073c9d207629cda74bd61604bf345053d797915346c4e531f9033b2df9067732f89d89f3e90b6ae92122c64c020964e7de5facd5784b66c76ac979829d886e8779f9b1f4b5e5efd954c956a916bb1d5f71937998aa33863da5ace9aa48432959190bfee853e57f55beeae4c6b8efcc0ff092f7f1f73afcd1daf3dcbb7c3f82fab45bacbc95366ad9fc6d495e5968e65c346248d49a759b29086e28a57f6af62769dfac85aba6ddf3013783b02ad9d872e8afa60d631a9f0c838298a5955222d611e3d1b79eb8a872beaa37fa5a9a00e50dabd0ca073bc1ff981bf906c0fda18164ae868587e9b802cdf7e26fae9a811f0b028401e6aa438408583b00840105fdbe84650a4b02b861d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a239e14e61ceb442e61edd782ed2e011994aca0236541d845851453ed45e1c950b3672dcc21546bd65e746c468b17a3722b7c529d64d9c3a4b41136ab03e48147e01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9e060a9b06f90318a0cc482c7a97c2c547a7e1483c14e65bb6087ca7257c15ff673f946298c57e7d90a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ee226379db83cffc681495730c11fdde79ba4c0ca0921e5a9881b361b462e86c18d8170303f37f3576c4298f951b164a3a0ffa7950a04a318f22b6185bdebef3900d7c65bcceed28c6906605406b54bd9eb07cb6a266a07a8d59ef980eed078ac8f192425c1fffbf5210a9c92a2065c40639f6421c2367b90100cae58a5a44a877dfab933564fb46b73ec4c3d9c7f068cd492e7b13a3d43cca90ce095bebe264c59a13537dd3575e47c5a87922ba687d73fbdf4cf75c5c7fae998edcc9956b64445fc973aacd815ef67bbc3ce25deb67e19207fff0d98cc0cd558a0ec9eb2bb7bee5b4e736041f80bdcb0862fbf2e9afff5e3ce0959b8fa1cfb795fe04f69cbfecdde7a927c01fe87cc89cad2e277b31e63a5619f6ffac97cb631f4ba69ce7fea3f16e3c2b15fb8b2462cbf6ef9b62b3e77173fb306f19eb12fbe2ecdedfb32acbcf3efa25d9f79838b2b76b25cec051447eab71740e862feb2fd214e4db5568ceb4a791b6bec6c1a972726641bce9fe4f68e46edf15df75e652028401e6aa448408583b00840107e57384650a4b05b90118d88301020a846765746888676f312e32302e34856c696e7578000000b19df4a2f8b5831dffffb860a4cc53efef08386da2bcdf2ccd02f5772899f7e1f3b0252b21bf309dd6f96034ee6570316f1767c75acdd7f6691589051341d1cdf1f118c5c47c505a2e48a47da6e7d26c3107799b8cf767cff1382115896c6b74f0df094690ee36d0fcecf95ef84c8401e6aa41a094904149695c8adb89cd6f020cb278275a2fd4483cfc10d7d3dab8121f69f3068401e6aa43a0cc482c7a97c2c547a7e1483c14e65bb6087ca7257c15ff673f946298c57e7d908093e10e56b7f84c8f756b3bd5422d93053db5f5a55dee436bae6d8066674e131f4f430278fc3cb1f4d9f3dd0c85410694b92887718d431d8ddf25524ece35d03501a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a04eedf58a08358d43f0d37410f1c301efcc3dd738eff0b07bb4f82c83f30a0cc2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ef0274e31810c9df02f98fafde0f841f4e66a1cda04773baafa2984559c063e6b1f50e3019baae941124e89d5d7bc3f009e484a3d0a0c350e76080e62e8e4f45c1d424daec63750b940344655e81f56f0c65f1e7ab40a0cfd21dbf9df8503fb97bcd511aa04483116eb7afd0d4702532d1ff0b8e8b849eb90100002e022444181418d2d2414984070420434880e00f19494c8452044a5a7001298681544650c412916e119ca3241220808c0110050418214674422800002620a06440c08029440f8f296082ac8214002db995a0c59de7580a06168014c01036205a8ca0628e8205000458ea6110210d480a002ce0809e0410430084100d4c6420390a20a40479e91a14982410089018c4902ca40d601091081181105024a110a007904082087e211261d6008c42ceb44942602191022801165326a8aa1f8f28f8e0262c92228732026080028c8812d2057a10b884800048b10c13545b9e20f6340ab485c910af5a940909064e044f41446c6b8581653051e81603b101fc498c0b028401e6aa458408583b008385259f84650a4b08b90118d88301020a846765746888676f312e32302e34856c696e7578000000b19df4a2f8b5831dffffb86088dd96fd990be352a39175463f3902ec9f4f036ed7cd8ab3ce3f4cc70dfc8230a1a1f856e28cbc84a4ed1f95431f63cd0464f1c2f061593bfaf3eae388264d02420af41cfc0e01525f438bc3cf11b9c5a988aa6bb9c82098d567b339709ac676f84c8401e6aa43a0cc482c7a97c2c547a7e1483c14e65bb6087ca7257c15ff673f946298c57e7d908401e6aa44a04eedf58a08358d43f0d37410f1c301efcc3dd738eff0b07bb4f82c83f30a0cc2801962735bca49e800156401aa4bbe2e32d58f36cc22ce3cfd8da23ca72e10eb2f44fa1c1a1840959059d86e6f1b936457795534d45c8a554c3060e9dd39ec108001a00000000000000000000000000000000000000000000000000000000000000000880000000000000000801200221400000000000000000000000000000000000000002a140000000000000000000000000000000000000000").to_vec(); + let header= hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212ed200ae9080ae608f90463a0794978ac680964fb5ada43366fa4d33a490c93ec6893304ddee68a59f2cafabaa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a09f0bb93d54df1fcbfd84d4173496de9cff0f403319bbbaf15791ccde774b73d8a03cd1ebc99cd975182c58de47be968c97658cff4c465e20654185f408a851403cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211308402625a008229a884669fb2e3b90223d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8048fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6ca7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98cb2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833309f8ae0fb860834538868d2c79371ead2f10fc7229fd3b3aaf1d7d8607fd7e1d2efba7df1008c105fdab4ad8029f86cfde1e3aa7dd24194fcf07502bb6c281fc3cbc08ad8cb467de57cbfd1bb93fabe72f77ece8f991a2b7a4d7fb301d54547c6cb4b612d06ff84882112ea042dfe9761fb9a677b088a868f237a171d511bea581f643844a1c98267902391882112fa0794978ac680964fb5ada43366fa4d33a490c93ec6893304ddee68a59f2cafaba80321f35c8454a2691a2efff6894cae6277ea06390978294fe0d10fe03f432fd07440d802ca0858a2d6138230b37d1a9148a3d76fbe8492854e637c9aad7494e3401a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa09696424e13500cdc742b049c6459c0bc4cb357eab5d9fb48a2e79787c8897a1fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211318402625a008084669fb2e6b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb860b6de9ffe941751cd11463bbd4bde69d3bc2b79868f669f9e2c4c327f036e6d558b013469a91670607dd88d63dc50b95d00719e118a17e5b72418b6ae4bef7aebbcdaa44b79f8c0677ac32c71312d84db44e6e9216bd84fb97c7d0701a4a03431f84882112fa0794978ac680964fb5ada43366fa4d33a490c93ec6893304ddee68a59f2cafaba821130a09696424e13500cdc742b049c6459c0bc4cb357eab5d9fb48a2e79787c8897a1f80e5619874ecb4463f8d86981d939ddb4d0eaa151c6080c7067788e06699789d0a415e921b8824e8adc7907e5bbccec9373b22c7fe8a48527e9348aa957871b63300a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a000000000000000000000000000000000000000000000000000000000000000000ad5060ad206f9034fa0e3aa9bc64f82ccd7e70ec415d73263d9da9f3bb44b78bed500033379df9be8aaa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d9a13701eafb76870cb220843b8c6476824bfa15a0558eacf75665a00d1eef186ffc4f79985db5e5fcb1aa24892df5d600ae869313a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028211328402625a008084669fb2e9b90111d98301040c846765746889676f312e32312e3132856c696e75780000d24ec9e8f8ae0fb86095a056c77bdeb59da26e665d69e75cc5667cd43df693a55f20f5f248483a3ce10cdd996b29c7fd6ba3f9e31cb4ac089c0b5bc13e77d83f17096d88f280b8d47ffd8b58b66bd760d0ccd4d26e0c2a7bb3ec168a06a815cfbdde9a2e18c32ac74ef848821130a09696424e13500cdc742b049c6459c0bc4cb357eab5d9fb48a2e79787c8897a1f821131a0e3aa9bc64f82ccd7e70ec415d73263d9da9f3bb44b78bed500033379df9be8aa80c04c6f70fa142c7486f7bed7e29a247f1203d58c7481c9aefef1193e6404112e32486f8d4dc8c7c558ae0b1bf860f6e05d425b7726ba7a4e2dac6e3e3eb83d3d00a0000000000000000000000000000000000000000000000000000000000000000088000000000000000080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000120310e8201a9506f90312f901f1a094e7dcd05ddcc3923085b451330f3aa5ce5a628d6685506d99cb09b3aef0e11ea065b83aa9b59125f9b090432f556c6ff947b5708eb11ca5ea26342392860be00aa0b116ef7733a93eed23f018027c116e60436a228a9f9173bb9b0c40eb71216da6a064c0a17f12a753c3fc032723866ac267ad8b7e05e7aa2e75bb680175d936617580a01a41c640130c53b3c90b1b5c691ed467218cee97aade5aac9306e72865851e27a004371241b9d6f35e1f361f2109d19a9192a9c0c749b2bd15fcb131a1a6ce5e3ba00577e3e2c4649c5a23cbdabe0bbfed7cdf6e85c136d84d58127cdec86264ad6ea070c0f30031f40c8017dbfc2ef008e6a3aae2e3105a654e0c5439b6104752882ea08f81903ec8515875682785142e1f92bdeaf65fccd5d0cf78b1ff2905a07e5883a03052420ba2d24a04d3f830584d3dbd6907b6d82bab84ddd806d03470e2c9d51ca06fb1a1498c2c8f93944a4f672ff4e982480ad181c835c0d8078159c517c7977aa013a426820f7b7249edc97cc5c002e653ac84b437f3ac12ac940c3d4b09e09827a09fbc54eac488b27315b09a1afa8d12f168e4c4cb5aea2d9a6ab5e7266da2f7e8a077c5e5cd5bd518bc509ee5e71790f1e42e492e23875b097e565cff8e809e7c8aa0a1575ef06513a19d2a28390e83958d2a3ffe166b530255b0fb5559d33409914d80f8b18080a0dc77b6ae50b675036e77b31973c79ec60c28c0d2c57b03ad99c2acfff2f0cd4e80a063a8a6161448a60a47ddbafa00899bed224e9f80072b35a1dbc64a82e85cd9b5a05e0f116451aaa1baab3f3abff2793c8318050eeed6bf62d464d343a11d86eb2880808080808080a0abbb1987d09a71106f586030d1ab913bae0008e2a7dec0d08f2d60cd30fb2ac8a096c706907bfc6472dd88315cb8e21ee6f60a661cd8050065e2ba387023ee96858080f869a020b1e2b1f9852058ee0aaadca3c963f77f6483a1a51c644d79386bcada360583b846f8440180a0e39304f0ec064a98e4b0a96432dfb0a9e4c7fd0f26a6bbcf9c75bff68c51a7a9a0b3d632130dcb5cb583b47ec0623e59ca3703e6e2564f144272b597f3e3511ba822448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2244a7876ea32e7a748c697d01345145485561305b24b6c305acd27ad7aff76367fd3a1dfe8da19afba969c8464f37a29e60923c3a85cfacbdef18daa782d5724f13d415f98c2244b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442244e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f83332a448fdaaa7e6631e438625ca25c857a3727ea28e565b876532dd999985816f1df35a5d6359177f1d49bfb3c20e25d6760197246ad0b6b8efb77ad316a0f31360c3733cabd6c2a44b2e42bc54d19116d2348ac83461e2e0915d508ad976963272de9af796035a7c68771d03c92709aa174ce1e8723cb6d7d1f6d960790e83c59e1f9867721e6302520a30a442a44d9a13701eafb76870cb220843b8c6476824bfa15b9ebdc1d1a70721d7f9c57622e0a5d1175df1e09672ab1e8909bf9a9433592107024bd8a3ad47fbbdca199ede96c50d22a44e04db2de85453e0936b441c339a26d10cfa71b50b359d8b4d1e5fd24f5a99712ed2e5a8f7180621828a1ae567b86ff60792ff27f2fd62d410aa8b9b858316495867f833330093808").to_vec(); let any: Any = header.try_into().unwrap(); let mut header = Header::try_from(any).unwrap(); - header.headers.all.pop(); + header.headers.all[1].extra_data = vec![]; let result = header.headers.verify_finalized(); match result.unwrap_err() { Error::UnexpectedVoteRelation(e1, e2, err) => { @@ -463,31 +429,25 @@ mod test { } } - #[test] - fn test_error_verify_too_many_headers_to_seal() { + #[rstest] + #[case::localnet(localnet())] + fn test_error_verify_too_many_headers_to_seal(#[case] hp: Box) { let v = vec![ - header_31297200(), - header_31297201(), - header_31297202(), - header_31297203(), - header_31297204(), - header_31297205(), - header_31297206(), - header_31297207(), - header_31297208(), - header_31297209(), - header_31297210(), + hp.epoch_header(), + hp.epoch_header_plus_1(), + hp.epoch_header_plus_2(), + hp.epoch_header_plus_3(), ]; - let c_val = v.first().unwrap().get_validator_set().unwrap(); - let c_val = EitherValidatorSet::Untrusted(untrust(&c_val)); + let c_val = v.first().unwrap().clone().epoch.unwrap(); + let c_val = EitherEpoch::Untrusted(untrust(&c_val)); let headers = ETHHeaders { target: v[0].clone(), all: v, }; - let p_val = validators_in_31297000().into(); + let p_val = Epoch::new(hp.previous_validators().into(), 1); let p_val = trust(&p_val); - let result = headers.verify(&mainnet(), &c_val, &p_val); + let result = headers.verify(&hp.network(), &c_val, &p_val); match result.unwrap_err() { Error::UnexpectedTooManyHeadersToFinalize(e1, e2) => { assert_eq!(e1, headers.target.number, "block error"); @@ -497,11 +457,12 @@ mod test { } } - #[test] - fn test_error_next_checkpoint_header_found_target_epoch() { + #[rstest] + #[case::localnet(localnet())] + fn test_error_next_checkpoint_header_found_target_epoch(#[case] hp: Box) { let f = |mut headers: ETHHeaders, - c_val: &EitherValidatorSet, - p_val: &TrustedValidatorSet, + c_val: &EitherEpoch, + p_val: &TrustedEpoch, include_limit: bool| { let epoch = headers.target.number / BLOCKS_PER_EPOCH; let next_epoch_checkpoint = (epoch + 1) * BLOCKS_PER_EPOCH + c_val.checkpoint(); @@ -515,7 +476,7 @@ mod test { next.number = last.number + 1; headers.all.push(next); } - let result = headers.verify(&mainnet(), c_val, p_val).unwrap_err(); + let result = headers.verify(&hp.network(), c_val, p_val).unwrap_err(); if include_limit { match result { Error::UnexpectedNextCheckpointHeader(e1, e2) => { @@ -531,27 +492,32 @@ mod test { }; } }; - let v = vec![header_31297200(), header_31297201(), header_31297202()]; + let v = vec![ + hp.epoch_header(), + hp.epoch_header_plus_1(), + hp.epoch_header_plus_2(), + ]; let headers = ETHHeaders { target: v[0].clone(), all: v, }; - let p_val = validators_in_31297000().into(); + let p_val = Epoch::new(hp.previous_validators().into(), 1); let p_val = trust(&p_val); - let c_val = header_31297200().get_validator_bytes().unwrap().into(); - let c_val = EitherValidatorSet::Untrusted(untrust(&c_val)); + let c_val = hp.epoch_header().epoch.unwrap(); + let c_val = EitherEpoch::Untrusted(untrust(&c_val)); f(headers.clone(), &c_val, &p_val, true); f(headers, &c_val, &p_val, false); } - #[test] - fn test_error_next_next_checkpoint_header_found() { + #[rstest] + #[case::localnet(localnet())] + fn test_error_next_next_checkpoint_header_found(#[case] hp: Box) { let f = |mut headers: ETHHeaders, - c_val: &EitherValidatorSet, - p_val: &TrustedValidatorSet, + c_val: &EitherEpoch, + p_val: &TrustedEpoch, n_val_header: ETHHeader, include_limit: bool| { - let n_val: ValidatorSet = n_val_header.get_validator_bytes().unwrap().into(); + let n_val = n_val_header.epoch.clone().unwrap(); let epoch = headers.target.number / BLOCKS_PER_EPOCH; let next_next_epoch_checkpoint = (epoch + 2) * BLOCKS_PER_EPOCH + n_val.checkpoint(); loop { @@ -564,11 +530,14 @@ mod test { next.number = last.number + 1; if next.is_epoch() { // set n_val - next.extra_data = n_val_header.extra_data.clone() + next.extra_data = n_val_header.extra_data.clone(); + let (validators, turn_length) = + get_validator_bytes_and_tern_term(&next.extra_data).unwrap(); + next.epoch = Some(Epoch::new(validators.into(), turn_length)); } headers.all.push(next); } - let result = headers.verify(&mainnet(), c_val, p_val).unwrap_err(); + let result = headers.verify(&hp.network(), c_val, p_val).unwrap_err(); if include_limit { match result { Error::UnexpectedNextNextCheckpointHeader(e1, e2) => { @@ -584,186 +553,28 @@ mod test { } } }; - let headers = create_after_checkpoint_headers(); - let c_val = header_31297200().get_validator_bytes().unwrap().into(); - let c_val = EitherValidatorSet::Trusted(trust(&c_val)); + let headers = hp.headers_after_checkpoint(); + let c_val = hp.epoch_header().epoch.unwrap(); + let c_val = EitherEpoch::Trusted(trust(&c_val)); let p_val = empty(); let p_val = trust(&p_val); - let n_val_header = header_31297200(); + let n_val_header = hp.epoch_header(); f(headers.clone(), &c_val, &p_val, n_val_header.clone(), true); f(headers, &c_val, &p_val, n_val_header.clone(), false); - let headers = create_before_checkpoint_headers(); - let p_val = validators_in_31297000().into(); + let headers = hp.headers_before_checkpoint(); + let p_val = Epoch::new(hp.previous_validators().into(), 1); let p_val = trust(&p_val); - let c_val = header_31297200().get_validator_bytes().unwrap().into(); - let c_val = EitherValidatorSet::Trusted(trust(&c_val)); + let c_val = hp.epoch_header().epoch.unwrap(); + let c_val = EitherEpoch::Trusted(trust(&c_val)); f(headers.clone(), &c_val, &p_val, n_val_header.clone(), true); - f(headers, &c_val, &p_val, header_31297200(), false); + f(headers, &c_val, &p_val, hp.epoch_header(), false); - let headers = create_across_checkpoint_headers(); + let headers = hp.headers_across_checkpoint(); f(headers.clone(), &c_val, &p_val, n_val_header.clone(), true); f(headers, &c_val, &p_val, n_val_header, false); } - #[test] - fn test_success_verify_non_neighboring_epoch() { - let headers: ETHHeaders = vec![ - header_31297200(), - header_31297201(), - header_31297202(), - header_31297203(), - header_31297204(), - header_31297205(), - header_31297206(), - header_31297207(), - header_31297208(), - header_31297209(), - header_31297210(), - header_31297211(), - header_31297212(), - header_31297213(), - ] - .into(); - - let checkpoint = - headers.target.number + ValidatorSet::from(validators_in_31297000()).checkpoint(); - let n_val_raw = header_31297200().get_validator_bytes().unwrap().into(); - let n_val = UntrustedValidatorSet::new(&n_val_raw); - let t_val_raw = validators_in_31297000().into(); - let t_val = TrustedValidatorSet::new(&t_val_raw); - headers - .verify_non_neighboring_epoch(&mainnet(), checkpoint, t_val, n_val) - .unwrap(); - } - - #[test] - fn test_error_verify_non_neighboring_epoch() { - let headers: ETHHeaders = vec![header_31297200()].into(); - - // Insufficient trustedValidators - let checkpoint = - headers.target.number + ValidatorSet::from(validators_in_31297000()).checkpoint(); - let n_val_raw = header_31297200().get_validator_bytes().unwrap().into(); - let n_val = UntrustedValidatorSet::new(&n_val_raw); - let t_val_raw = vec![vec![0], vec![1], vec![2]].into(); - let t_val = TrustedValidatorSet::new(&t_val_raw); - let err = headers - .verify_non_neighboring_epoch(&mainnet(), checkpoint, t_val, n_val) - .unwrap_err(); - match err { - Error::InsufficientTrustedValidatorsInUntrustedValidators(_, found, required) => { - assert_eq!(found, 0); - assert_eq!(required, 1); - } - err => unreachable!("unexpected error type {:?}", err), - } - - // illegal sequence - let headers: ETHHeaders = vec![header_31297200(), header_31297202()].into(); - let n_val_raw = header_31297200().get_validator_bytes().unwrap().into(); - let n_val = UntrustedValidatorSet::new(&n_val_raw); - let t_val_raw = validators_in_31297000().into(); - let t_val = TrustedValidatorSet::new(&t_val_raw); - let err = headers - .verify_non_neighboring_epoch(&mainnet(), checkpoint, t_val, n_val) - .unwrap_err(); - match err { - Error::UnexpectedHeaderRelation(h1, h2, _, _, _, _) => { - assert_eq!(h1, 31297200); - assert_eq!(h2, 31297202); - } - err => unreachable!("unexpected error type {:?}", err), - } - - // illegal sealer after checkpoint - let mut headers: ETHHeaders = vec![ - header_31297200(), - header_31297201(), - header_31297202(), - header_31297203(), - header_31297204(), - header_31297205(), - header_31297206(), - header_31297207(), - header_31297208(), - header_31297209(), - header_31297210(), - header_31297211(), - header_31297212(), - header_31297213(), - ] - .into(); - headers.all.last_mut().unwrap().coinbase = vec![]; - let n_val_raw = header_31297200().get_validator_bytes().unwrap().into(); - let n_val = UntrustedValidatorSet::new(&n_val_raw); - let t_val_raw = validators_in_31297000().into(); - let t_val = TrustedValidatorSet::new(&t_val_raw); - let err = headers - .verify_non_neighboring_epoch(&mainnet(), checkpoint, t_val, n_val) - .unwrap_err(); - match err { - Error::UnexpectedCoinbase(h1) => { - assert_eq!(h1, 31297213); - } - err => unreachable!("unexpected error type {:?}", err), - } - - // invalid header size - let headers: ETHHeaders = vec![ - header_31297200(), - header_31297201(), - header_31297202(), - header_31297203(), - header_31297204(), - header_31297205(), - header_31297206(), - header_31297207(), - header_31297208(), - header_31297209(), - header_31297210(), - header_31297211(), - header_31297212(), - ] - .into(); - let n_val_raw = header_31297200().get_validator_bytes().unwrap().into(); - let n_val = UntrustedValidatorSet::new(&n_val_raw); - let t_val_raw = validators_in_31297000().into(); - let t_val = TrustedValidatorSet::new(&t_val_raw); - let err = headers - .verify_non_neighboring_epoch(&mainnet(), checkpoint, t_val, n_val) - .unwrap_err(); - match err { - Error::InvalidVerifyingHeaderLength(h1, size) => { - assert_eq!(h1, 31297200); - assert_eq!(size, 2); - } - err => unreachable!("unexpected error type {:?}", err), - } - } - - fn create_before_checkpoint_headers() -> ETHHeaders { - vec![header_31297208(), header_31297209(), header_31297210()].into() - } - - fn create_across_checkpoint_headers() -> ETHHeaders { - vec![ - header_31297210(), - header_31297211(), // checkpoint - header_31297212(), - ] - .into() - } - - fn create_after_checkpoint_headers() -> ETHHeaders { - vec![ - header_31297211(), // checkpoint - header_31297212(), - header_31297213(), - ] - .into() - } - impl From> for ETHHeaders { fn from(value: Vec) -> Self { Self { diff --git a/light-client/src/header/mod.rs b/light-client/src/header/mod.rs index 65d9fc0..f87c04f 100644 --- a/light-client/src/header/mod.rs +++ b/light-client/src/header/mod.rs @@ -8,12 +8,11 @@ use parlia_ibc_proto::ibc::lightclients::parlia::v1::Header as RawHeader; use crate::commitment::decode_eip1184_rlp_proof; use crate::consensus_state::ConsensusState; -use crate::header::eth_header::ETHHeader; + +use crate::header::epoch::{EitherEpoch, Epoch, TrustedEpoch, UntrustedEpoch}; +use crate::header::eth_header::{validate_turn_length, ETHHeader}; use crate::header::eth_headers::ETHHeaders; -use crate::header::validator_set::{ - EitherValidatorSet, TrustedValidatorSet, UntrustedValidatorSet, ValidatorSet, -}; use crate::misc::{new_height, new_timestamp, ChainId, Hash}; use super::errors::Error; @@ -29,17 +28,15 @@ pub mod eth_headers; pub mod validator_set; pub mod vote_attestation; +pub mod epoch; + #[derive(Clone, Debug, PartialEq)] pub struct Header { account_proof: Vec, headers: ETHHeaders, trusted_height: Height, - previous_validators: ValidatorSet, - /// validator set - /// - not a epoch block: current epoch validators (which must be in trusted cons state) - /// - non neighboring epoch header: validators in trusted cons state - /// - neighboring epoch header: validators in extra data - current_validators: ValidatorSet, + previous_epoch: Epoch, + current_epoch: Epoch, } impl Header { @@ -67,16 +64,11 @@ impl Header { } pub fn previous_epoch_validators_hash(&self) -> Hash { - self.previous_validators.hash + self.previous_epoch.hash() } - /// In non-adjacent epochs, current_validators contains the validator set of trusted_height, - /// so you need to use the validator set of extra_data of target. - pub fn current_epoch_validators_hash(&self) -> Result { - if self.headers.target.is_epoch() { - return Ok(self.headers.target.get_validator_set()?.hash); - } - Ok(self.current_validators.hash) + pub fn current_epoch_validators_hash(&self) -> Hash { + self.current_epoch.hash() } pub fn block_hash(&self) -> &Hash { @@ -88,80 +80,26 @@ impl Header { chain_id: &ChainId, consensus_state: &ConsensusState, ) -> Result<(), Error> { - if self.is_non_neighboring_epoch() { - let n_val = self.headers.target.get_validator_set()?; - // 'current_validators' are trusted validators in non-neighboring epoch verification. - let t_val = &self.current_validators; - let (t_val, n_val) = verify_validator_set_non_neighboring_epoch( - consensus_state, - self.height(), - self.trusted_height(), - t_val, - &n_val, - )?; - - // target height is epoch - let checkpoint = - self.height().revision_height() + self.previous_validators.checkpoint(); - self.headers - .verify_non_neighboring_epoch(chain_id, checkpoint, t_val, n_val) - } else { - let (c_val, p_val) = verify_validator_set( - consensus_state, - &self.headers.target, - self.height(), - self.trusted_height, - &self.previous_validators, - &self.current_validators, - )?; - self.headers.verify(chain_id, &c_val, &p_val) - } - } - - fn is_non_neighboring_epoch(&self) -> bool { - if !self.headers.target.is_epoch() { - return false; - } - let trusted_epoch = self.trusted_height.revision_height() / BLOCKS_PER_EPOCH; - let target_epoch = self.height().revision_height() / BLOCKS_PER_EPOCH; - trusted_epoch + 1 < target_epoch + let (c_val, p_val) = verify_epoch( + consensus_state, + &self.headers.target, + self.height(), + self.trusted_height, + &self.previous_epoch, + &self.current_epoch, + )?; + self.headers.verify(chain_id, &c_val, &p_val) } } -fn verify_validator_set_non_neighboring_epoch<'a>( - consensus_state: &ConsensusState, - height: Height, - trusted_height: Height, - current_validators: &'a ValidatorSet, - next_validators: &'a ValidatorSet, -) -> Result<(TrustedValidatorSet<'a>, UntrustedValidatorSet<'a>), Error> { - if current_validators.validators.is_empty() { - return Err(Error::MissingTrustedCurrentValidators( - height.revision_height(), - )); - } - if consensus_state.current_validators_hash != current_validators.hash { - return Err(Error::UnexpectedCurrentValidatorsHash( - trusted_height, - height, - current_validators.hash, - consensus_state.previous_validators_hash, - )); - } - Ok(( - TrustedValidatorSet::new(current_validators), - UntrustedValidatorSet::new(next_validators), - )) -} - -fn verify_validator_set<'a>( +fn verify_epoch<'a>( consensus_state: &ConsensusState, target: ÐHeader, height: Height, trusted_height: Height, - previous_validators: &'a ValidatorSet, - current_validators: &'a ValidatorSet, -) -> Result<(EitherValidatorSet<'a>, TrustedValidatorSet<'a>), Error> { + previous_epoch: &'a Epoch, + current_epoch: &'a Epoch, +) -> Result<(EitherEpoch<'a>, TrustedEpoch<'a>), Error> { let is_epoch = target.is_epoch(); let header_epoch = height.revision_height() / BLOCKS_PER_EPOCH; let trusted_epoch = trusted_height.revision_height() / BLOCKS_PER_EPOCH; @@ -173,29 +111,32 @@ fn verify_validator_set<'a>( height.revision_height(), )); } - let previous_trusted = previous_validators.hash == consensus_state.current_validators_hash; + let previous_trusted = previous_epoch.hash() == consensus_state.current_validators_hash; if !previous_trusted { - return Err(Error::UnexpectedPreviousValidatorsHash( + return Err(Error::UnexpectedUntrustedValidatorsHashInEpoch( trusted_height, height, - previous_validators.hash, + previous_epoch.hash(), consensus_state.current_validators_hash, )); } - let val_in_extra = target.get_validator_set()?; - if val_in_extra.hash != current_validators.hash { - return Err(Error::UnexpectedCurrentValidatorsHash( + let epoch_info = target + .epoch + .as_ref() + .ok_or_else(|| Error::MissingEpochInfoInEpochBlock(target.number))?; + if epoch_info.hash() != current_epoch.hash() { + return Err(Error::UnexpectedCurrentValidatorsHashInEpoch( trusted_height, height, - val_in_extra.hash, - current_validators.hash, + epoch_info.hash(), + current_epoch.hash(), )); } Ok(( - EitherValidatorSet::Untrusted(UntrustedValidatorSet::new(current_validators)), - TrustedValidatorSet::new(previous_validators), + EitherEpoch::Untrusted(UntrustedEpoch::new(current_epoch)), + TrustedEpoch::new(previous_epoch), )) } else { if header_epoch != trusted_epoch { @@ -204,27 +145,27 @@ fn verify_validator_set<'a>( height.revision_height(), )); } - let previous_trusted = previous_validators.hash == consensus_state.previous_validators_hash; + let previous_trusted = previous_epoch.hash() == consensus_state.previous_validators_hash; if !previous_trusted { return Err(Error::UnexpectedPreviousValidatorsHash( trusted_height, height, - previous_validators.hash, + previous_epoch.hash(), consensus_state.previous_validators_hash, )); } - let current_trusted = current_validators.hash == consensus_state.current_validators_hash; + let current_trusted = current_epoch.hash() == consensus_state.current_validators_hash; if !current_trusted { return Err(Error::UnexpectedCurrentValidatorsHash( trusted_height, height, - current_validators.hash, + current_epoch.hash(), consensus_state.current_validators_hash, )); } Ok(( - EitherValidatorSet::Trusted(TrustedValidatorSet::new(current_validators)), - TrustedValidatorSet::new(previous_validators), + EitherEpoch::Trusted(TrustedEpoch::new(current_epoch)), + TrustedEpoch::new(previous_epoch), )) } } @@ -255,17 +196,35 @@ impl TryFrom for Header { if value.previous_validators.is_empty() { return Err(Error::MissingPreviousValidators(headers.target.number)); } - - if value.current_validators.is_empty() { + validate_turn_length(value.previous_turn_length as u8)?; + + // Epoch header contains validator set + let current_epoch = if headers.target.is_epoch() { + headers + .target + .epoch + .clone() + .ok_or_else(|| Error::MissingEpochInfoInEpochBlock(headers.target.number))? + } else { + Epoch::new( + value.current_validators.into(), + value.current_turn_length as u8, + ) + }; + if current_epoch.validators().is_empty() { return Err(Error::MissingCurrentValidators(headers.target.number)); } + validate_turn_length(value.current_turn_length as u8)?; Ok(Self { account_proof: value.account_proof, headers, trusted_height, - previous_validators: value.previous_validators.into(), - current_validators: value.current_validators.into(), + previous_epoch: Epoch::new( + value.previous_validators.into(), + value.previous_turn_length as u8, + ), + current_epoch, }) } } @@ -290,39 +249,64 @@ impl TryFrom for Header { } } -#[cfg(test)] -pub(crate) mod testdata; - #[cfg(test)] pub(crate) mod test { use crate::consensus_state::ConsensusState; use crate::errors::Error; - use crate::header::constant::BLOCKS_PER_EPOCH; + use crate::fixture::*; + use crate::header::epoch::{EitherEpoch, Epoch}; use crate::header::eth_headers::ETHHeaders; - use crate::header::testdata::{header_31297200, header_31297201, validators_in_31297000}; - use crate::header::validator_set::{EitherValidatorSet, ValidatorSet}; - use crate::header::{verify_validator_set, verify_validator_set_non_neighboring_epoch, Header}; + use crate::header::validator_set::ValidatorSet; + use crate::header::{verify_epoch, Header}; use crate::misc::{new_height, Hash, Validators}; - use light_client::types::Time; + use alloc::boxed::Box; + use alloc::vec::Vec; + use hex_literal::hex; + use light_client::types::{Any, Height as LCPHeight, Time}; use parlia_ibc_proto::ibc::core::client::v1::Height; - use parlia_ibc_proto::ibc::lightclients::parlia::v1::Header as RawHeader; + use parlia_ibc_proto::ibc::lightclients::parlia::v1::{EthHeader, Header as RawHeader}; + use rstest::rstest; impl Header { pub(crate) fn eth_header(&self) -> ÐHeaders { &self.headers } + + pub(crate) fn new( + account_proof: Vec, + headers: ETHHeaders, + trusted_height: Height, + previous_epoch: Epoch, + current_epoch: Epoch, + ) -> Self { + Self { + account_proof, + headers, + trusted_height: LCPHeight::new( + trusted_height.revision_number, + trusted_height.revision_height, + ), + previous_epoch, + current_epoch, + } + } } - #[test] - fn test_error_try_from_missing_trusted_height() { - let h = &header_31297201(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_try_from_missing_trusted_height(#[case] hp: Box) { + let h = &hp.epoch_header_plus_1(); let raw = RawHeader { - headers: vec![h.try_into().unwrap()], + headers: vec![EthHeader { + header: hp.epoch_header_plus_1_rlp(), + }], trusted_height: None, account_proof: vec![], current_validators: vec![h.coinbase.clone()], previous_validators: vec![h.coinbase.clone()], + current_turn_length: 1, + previous_turn_length: 1, }; let err = Header::try_from(raw).unwrap_err(); match err { @@ -331,19 +315,24 @@ pub(crate) mod test { } } - #[test] - fn test_error_try_from_unexpected_trusted_height() { - let h = &header_31297201(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_try_from_unexpected_trusted_height(#[case] hp: Box) { + let h = &hp.epoch_header_plus_1(); let trusted_height = Height { revision_number: 0, revision_height: h.number, }; let raw = RawHeader { - headers: vec![h.try_into().unwrap()], + headers: vec![EthHeader { + header: hp.epoch_header_plus_1_rlp(), + }], trusted_height: Some(trusted_height.clone()), account_proof: vec![], current_validators: vec![h.coinbase.clone()], previous_validators: vec![h.coinbase.clone()], + current_turn_length: 1, + previous_turn_length: 1, }; let err = Header::try_from(raw).unwrap_err(); match err { @@ -355,19 +344,24 @@ pub(crate) mod test { } } - #[test] - fn test_error_try_from_previous_validators_is_empty() { - let h = &header_31297201(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_try_from_previous_validators_is_empty(#[case] hp: Box) { + let h = &hp.epoch_header_plus_1(); let trusted_height = Height { revision_number: 0, revision_height: h.number - 1, }; let raw = RawHeader { - headers: vec![h.try_into().unwrap()], + headers: vec![EthHeader { + header: hp.epoch_header_plus_1_rlp(), + }], trusted_height: Some(trusted_height), account_proof: vec![], current_validators: vec![h.coinbase.clone()], previous_validators: vec![], + current_turn_length: 1, + previous_turn_length: 1, }; let err = Header::try_from(raw).unwrap_err(); match err { @@ -378,19 +372,24 @@ pub(crate) mod test { } } - #[test] - fn test_error_try_from_current_validators_is_empty() { - let h = &header_31297201(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_try_from_current_validators_is_empty(#[case] hp: Box) { + let h = &hp.epoch_header_plus_1(); let trusted_height = Height { revision_number: 0, revision_height: h.number - 1, }; let raw = RawHeader { - headers: vec![h.try_into().unwrap()], + headers: vec![EthHeader { + header: hp.epoch_header_plus_1_rlp(), + }], trusted_height: Some(trusted_height), account_proof: vec![], current_validators: vec![], previous_validators: vec![h.coinbase.clone()], + current_turn_length: 1, + previous_turn_length: 1, }; let err = Header::try_from(raw).unwrap_err(); match err { @@ -401,53 +400,24 @@ pub(crate) mod test { } } - #[test] - fn test_success_try_from() { - let h = &header_31297200(); - let trusted_height = Height { - revision_number: 0, - revision_height: h.number - 1, - }; - let raw = RawHeader { - headers: vec![h.try_into().unwrap()], - trusted_height: Some(trusted_height.clone()), - account_proof: vec![], - current_validators: header_31297200().get_validator_bytes().unwrap(), - previous_validators: validators_in_31297000(), - }; - let result = Header::try_from(raw.clone()).unwrap(); - assert_eq!(result.headers.target, *h); - assert_eq!( - result.trusted_height.revision_height(), - trusted_height.revision_height - ); - assert_eq!( - result.trusted_height.revision_number(), - trusted_height.revision_number - ); - assert_eq!( - &result.previous_validators.validators, - &raw.previous_validators - ); - assert_eq!( - &result.current_validators.validators, - &raw.current_validators - ); - } - - #[test] - fn test_success_try_from2() { - let h = &header_31297201(); + #[rstest] + #[case::localnet(localnet())] + fn test_success_try_from(#[case] hp: Box) { + let h = &hp.epoch_header(); let trusted_height = Height { revision_number: 0, revision_height: h.number - 1, }; let raw = RawHeader { - headers: vec![h.try_into().unwrap()], + headers: vec![EthHeader { + header: hp.epoch_header_rlp(), + }], trusted_height: Some(trusted_height.clone()), account_proof: vec![], - current_validators: vec![header_31297200().coinbase], - previous_validators: vec![h.coinbase.clone()], + current_validators: hp.epoch_header().epoch.unwrap().validators().clone(), + previous_validators: hp.previous_validators(), + current_turn_length: 1, + previous_turn_length: 1, }; let result = Header::try_from(raw.clone()).unwrap(); assert_eq!(result.headers.target, *h); @@ -459,14 +429,8 @@ pub(crate) mod test { result.trusted_height.revision_number(), trusted_height.revision_number ); - assert_eq!( - &result.previous_validators.validators, - &raw.previous_validators - ); - assert_eq!( - &result.current_validators.validators, - &raw.current_validators - ); + assert_eq!(result.previous_epoch.validators(), &raw.previous_validators); + assert_eq!(result.current_epoch.validators(), &raw.current_validators); } fn to_validator_set(h: Hash) -> ValidatorSet { @@ -476,31 +440,32 @@ pub(crate) mod test { v } - #[test] - fn test_success_verify_validator_set() { + #[rstest] + #[case::localnet(localnet())] + fn test_success_verify_validator_set(#[case] hp: Box) { let cs = ConsensusState { state_root: [0u8; 32], timestamp: Time::now(), - current_validators_hash: [1u8; 32], - previous_validators_hash: [2u8; 32], + current_validators_hash: Epoch::new(to_validator_set([1u8; 32]), 1).hash(), + previous_validators_hash: Epoch::new(to_validator_set([2u8; 32]), 1).hash(), }; // epoch let height = new_height(0, 400); let trusted_height = new_height(0, 201); - let current_validators = &header_31297200().get_validator_set().unwrap(); - let previous_validators = &to_validator_set(cs.current_validators_hash); - let (c_val, p_val) = verify_validator_set( + let current_epoch = &hp.epoch_header().epoch.unwrap(); + let previous_epoch = &Epoch::new(to_validator_set([1u8; 32]), 1); + let (c_val, p_val) = verify_epoch( &cs, - &header_31297200(), + &hp.epoch_header(), height, trusted_height, - previous_validators, - current_validators, + previous_epoch, + current_epoch, ) .unwrap(); match c_val { - EitherValidatorSet::Untrusted(r) => { + EitherEpoch::Untrusted(r) => { assert!(r.try_borrow(&p_val).is_err()) } _ => unreachable!("unexpected trusted"), @@ -510,50 +475,51 @@ pub(crate) mod test { let cs = ConsensusState { state_root: [0u8; 32], timestamp: Time::now(), - current_validators_hash: [1u8; 32], - previous_validators_hash: [2u8; 32], + current_validators_hash: Epoch::new(to_validator_set([1u8; 32]), 1).hash(), + previous_validators_hash: Epoch::new(to_validator_set([2u8; 32]), 1).hash(), }; let height = new_height(0, 599); let trusted_height = new_height(0, 400); - let current_validators = &to_validator_set(cs.current_validators_hash); - let previous_validators = &to_validator_set(cs.previous_validators_hash); - let (c_val, _p_val) = verify_validator_set( + let current_epoch = &Epoch::new(to_validator_set([1u8; 32]), 1); + let previous_epoch = &Epoch::new(to_validator_set([2u8; 32]), 1); + let (c_val, _p_val) = verify_epoch( &cs, - &header_31297201(), + &hp.epoch_header_plus_1(), height, trusted_height, - previous_validators, - current_validators, + previous_epoch, + current_epoch, ) .unwrap(); match c_val { - EitherValidatorSet::Trusted(r) => { - assert_eq!(*r.validators(), current_validators.validators); + EitherEpoch::Trusted(r) => { + assert_eq!(r.validators(), current_epoch.validators()); } _ => unreachable!("unexpected untrusted"), } } - #[test] - fn test_error_verify_validator_set() { + #[rstest] + #[case::localnet(localnet())] + fn test_error_verify_validator_set(#[case] hp: Box) { let cs = ConsensusState { state_root: [0u8; 32], timestamp: Time::now(), - current_validators_hash: [1u8; 32], - previous_validators_hash: [2u8; 32], + current_validators_hash: Epoch::new(to_validator_set([1u8; 32]), 1).hash(), + previous_validators_hash: Epoch::new(to_validator_set([2u8; 32]), 1).hash(), }; let height = new_height(0, 400); let trusted_height = new_height(0, 199); - let current_validators = &to_validator_set([1u8; 32]); - let previous_validators = &to_validator_set([2u8; 32]); - let err = verify_validator_set( + let current_epoch = &Epoch::new(to_validator_set([1u8; 32]), 1); + let previous_epoch = &Epoch::new(to_validator_set([2u8; 32]), 1); + let err = verify_epoch( &cs, - &header_31297200(), + &hp.epoch_header(), height, trusted_height, - previous_validators, - current_validators, + previous_epoch, + current_epoch, ) .unwrap_err(); match err { @@ -565,35 +531,34 @@ pub(crate) mod test { } let trusted_height = new_height(0, 200); - let previous_validators = &to_validator_set([3u8; 32]); - let err = verify_validator_set( + let err = verify_epoch( &cs, - &header_31297200(), + &hp.epoch_header(), height, trusted_height, - previous_validators, - current_validators, + previous_epoch, + current_epoch, ) .unwrap_err(); match err { - Error::UnexpectedPreviousValidatorsHash(t, h, hash, cons_hash) => { + Error::UnexpectedUntrustedValidatorsHashInEpoch(t, h, hash, cons_hash) => { assert_eq!(t, trusted_height); assert_eq!(h, height); - assert_eq!(hash, previous_validators.hash); - assert_eq!(cons_hash, cons_hash); + assert_eq!(hash, previous_epoch.hash()); + assert_eq!(cons_hash, cs.current_validators_hash); } _ => unreachable!("err {:?}", err), } let height = new_height(0, 401); let trusted_height = new_height(0, 200); - let err = verify_validator_set( + let err = verify_epoch( &cs, - &header_31297201(), + &hp.epoch_header_plus_1(), height, trusted_height, - previous_validators, - current_validators, + previous_epoch, + current_epoch, ) .unwrap_err(); match err { @@ -605,45 +570,45 @@ pub(crate) mod test { } let trusted_height = new_height(0, 400); - let current_validators = &to_validator_set([1u8; 32]); - let previous_validators = &to_validator_set([3u8; 32]); - let err = verify_validator_set( + let current_epoch = &Epoch::new(to_validator_set([1u8; 32]), 1); + let previous_epoch = &Epoch::new(to_validator_set([3u8; 32]), 1); + let err = verify_epoch( &cs, - &header_31297201(), + &hp.epoch_header_plus_1(), height, trusted_height, - previous_validators, - current_validators, + previous_epoch, + current_epoch, ) .unwrap_err(); match err { Error::UnexpectedPreviousValidatorsHash(t, h, hash, cons_hash) => { assert_eq!(t, trusted_height); assert_eq!(h, height); - assert_eq!(hash, previous_validators.hash); - assert_eq!(cons_hash, cons_hash); + assert_eq!(hash, previous_epoch.hash()); + assert_eq!(cons_hash, cs.previous_validators_hash); } _ => unreachable!("err {:?}", err), } let trusted_height = new_height(0, 400); - let current_validators = &to_validator_set([3u8; 32]); - let previous_validators = &to_validator_set([2u8; 32]); - let err = verify_validator_set( + let current_epoch = &Epoch::new(to_validator_set([3u8; 32]), 1); + let previous_epoch = &Epoch::new(to_validator_set([2u8; 32]), 1); + let err = verify_epoch( &cs, - &header_31297201(), + &hp.epoch_header_plus_1(), height, trusted_height, - previous_validators, - current_validators, + previous_epoch, + current_epoch, ) .unwrap_err(); match err { Error::UnexpectedCurrentValidatorsHash(t, h, hash, cons_hash) => { assert_eq!(t, trusted_height); assert_eq!(h, height); - assert_eq!(hash, current_validators.hash); - assert_eq!(cons_hash, cons_hash); + assert_eq!(hash, current_epoch.hash()); + assert_eq!(cons_hash, cs.current_validators_hash); } _ => unreachable!("err {:?}", err), } @@ -651,141 +616,43 @@ pub(crate) mod test { let cs = ConsensusState { state_root: [0u8; 32], timestamp: Time::now(), - current_validators_hash: [4u8; 32], - previous_validators_hash: [2u8; 32], + current_validators_hash: Epoch::new(to_validator_set([4u8; 32]), 1).hash(), + previous_validators_hash: Epoch::new(to_validator_set([2u8; 32]), 1).hash(), }; let height = new_height(0, 400); let trusted_height = new_height(0, 399); - let current_validators = &to_validator_set([1u8; 32]); - let previous_validators = &to_validator_set([4u8; 32]); - let err = verify_validator_set( + let current_epoch = &Epoch::new(to_validator_set([1u8; 32]), 1); + let previous_epoch = &Epoch::new(to_validator_set([4u8; 32]), 1); + let err = verify_epoch( &cs, - &header_31297200(), + &hp.epoch_header(), height, trusted_height, - previous_validators, - current_validators, + previous_epoch, + current_epoch, ) .unwrap_err(); match err { - Error::UnexpectedCurrentValidatorsHash(t, h, header_hash, request_hash) => { + Error::UnexpectedCurrentValidatorsHashInEpoch(t, h, header_hash, request_hash) => { assert_eq!(t, trusted_height); assert_eq!(h, height); - assert_eq!( - header_hash, - header_31297200().get_validator_set().unwrap().hash - ); - assert_eq!(request_hash, current_validators.hash); + assert_eq!(header_hash, hp.epoch_header().epoch.unwrap().hash()); + assert_eq!(request_hash, current_epoch.hash()); } _ => unreachable!("err {:?}", err), } } #[test] - fn test_success_verify_validator_set_non_neighboring_epoch() { - let cs = ConsensusState { - state_root: [0u8; 32], - timestamp: Time::now(), - current_validators_hash: [1u8; 32], - previous_validators_hash: [2u8; 32], - }; - - let height = new_height(0, 600); - let trusted_height = new_height(0, 201); - - let trusted_validators = &to_validator_set(cs.current_validators_hash); - let next_validators = &to_validator_set([4u8; 32]); - let (_c_val, _n_val) = verify_validator_set_non_neighboring_epoch( - &cs, - height, - trusted_height, - trusted_validators, - next_validators, - ) - .unwrap(); - } - - #[test] - fn test_error_verify_validator_set_non_neighboring_epoch() { - let cs = ConsensusState { - state_root: [0u8; 32], - timestamp: Time::now(), - current_validators_hash: [1u8; 32], - previous_validators_hash: [2u8; 32], - }; - - let height = new_height(0, 600); - let trusted_height = new_height(0, 201); - - // empty trusted validator - let mut trusted_validators = to_validator_set(cs.current_validators_hash); - trusted_validators.validators = Validators::new(); - let next_validators = &to_validator_set([4u8; 32]); - let err = verify_validator_set_non_neighboring_epoch( - &cs, - height, - trusted_height, - &trusted_validators, - next_validators, - ) - .unwrap_err(); + fn test_error_try_from_invalid_turn_length() { + let header= hex!("0a222f6962632e6c69676874636c69656e74732e7061726c69612e76312e48656164657212961e0a9e060a9b06f90318a0793f4896c559772686c55bc1140baa291e62ef268061713080c9d02193ecd549a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794d1d6bf74282782b0b3eb1413c901d6ecf02e8e28a0c2081e9bb02adf2b65cf9b3f83b71142e4a963584516174fa671c75e3c9b82f0a071f511f91544d703b0a8a74ef6b93df3d261d961b15f5abb688a115a164f59aba0a93cf4b9598e6c8ff24b4aea19f8a64291de129c57118291fee8c4b16de22fe5b90100462586c2f1cfbc9f58faae6f8ff10b2b6a5e6acb0d3077c87e9b05031ab93d1e8f62b32a766618ad9af4b9a1629f42008273c409768e35be70154b2721e87ef585d19504837158efa1b705d99333122ea79c48b387729b7e491f8154d55c5f180e6d01668a76152594e3183ccae8490d8e8e92500e0f5c2ad6b0e415f45ac72f95fab24672835de1c48e0a9f38923ec496ae5dd5fb62043cfd7bc0c8f0c5c3f1670ef7d1d7fc2b907ffe63ced34467b8fbf2300dba03b63a57722ff07ae56961f52d1a32862a09ef3698d1b93bc636286a56b3cadb8b22998372f4c28cd1e72c7ab0f0ab0db8c6aa8105556c1a3481c6fc66ac24d5ae775fba850d343a210feb028401e6aa4184084fe2c684014933a184650a4afbb90118d88301020b846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5831dffffb8609865f38b886fdf9133435031ff4e3af35f0f7dcd165bed2f80f523864cdcaacd102a5d538972060573218a8cbd201d9418fde9d217990d8faf5c5c382618820fe24cf490f1010d92a66114d3d5305e953ef00268448068d5fb4638a94c4269a2f84c8401e6aa3fa0cba1480655a9172eb8fc0a0ea9cd5a285b9fcea8489bde764a134c52a8cc0ff98401e6aa40a0793f4896c559772686c55bc1140baa291e62ef268061713080c9d02193ecd54980a72fc8f10e414df8a61ea1d4d2f3362b2fa0c8c7c444848769e6d67bdbcce4de2683fdae80bcd5a90a8f92d76b7ae426f11d51a7f1d785fefe1cbf451f67186401a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9a060a9706f90314a094904149695c8adb89cd6f020cb278275a2fd4483cfc10d7d3dab8121f69f306a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e9ae3261a475a27bb1028f140bc2a7c843318afda0c2081e9bb02adf2b65cf9b3f83b71142e4a963584516174fa671c75e3c9b82f0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028401e6aa4284085832a78084650a4affb90118d88301020a846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5831dffffb860b02f4314b40616294282cb1f66df8eb23b1c26395b214e78ecd75a9646e0fd008b5f9bae4b24647db4f4b4a92ca0aee4032f3a8917546bfc7c078624ab1b0be6bf87972f4d9815f4f96ad00ba291308ee5c5f6c63243e9518ab6c1f42ce34470f84c8401e6aa40a0793f4896c559772686c55bc1140baa291e62ef268061713080c9d02193ecd5498401e6aa41a094904149695c8adb89cd6f020cb278275a2fd4483cfc10d7d3dab8121f69f30680ec8e7cec4b6c25fa8b22c40e9ecae359c542137ed189c711f5cd7616f4619f331f3eb09268047aaf47af3b83786ee4471c31779848627720f48a7bf5ca50f14601a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800ae6040ae304f90260a0cadbcaaebd901c23537425e903b40a054d6cca192f0f01ecf3d45d9afce4cef3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ea0a6e3c511bbd10f4519ece37dc24887e11b55da054d3ce938c69efbd57808ae22c9030bfa64ebfe6b7f16d5574b1fada5c336d96a0ba3499b3199bc9606a46f865d4abc0cfa9e1be68940ba8a91eb0de4e02d660f5a04278f75943cad9584a22440799ef5f5db6618e33bed532b709b859bb44e0d02fb901006eb746324da2c67a4c1a4a70aeed04073c9d207629cda74bd61604bf345053d797915346c4e531f9033b2df9067732f89d89f3e90b6ae92122c64c020964e7de5facd5784b66c76ac979829d886e8779f9b1f4b5e5efd954c956a916bb1d5f71937998aa33863da5ace9aa48432959190bfee853e57f55beeae4c6b8efcc0ff092f7f1f73afcd1daf3dcbb7c3f82fab45bacbc95366ad9fc6d495e5968e65c346248d49a759b29086e28a57f6af62769dfac85aba6ddf3013783b02ad9d872e8afa60d631a9f0c838298a5955222d611e3d1b79eb8a872beaa37fa5a9a00e50dabd0ca073bc1ff981bf906c0fda18164ae868587e9b802cdf7e26fae9a811f0b028401e6aa438408583b00840105fdbe84650a4b02b861d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a239e14e61ceb442e61edd782ed2e011994aca0236541d845851453ed45e1c950b3672dcc21546bd65e746c468b17a3722b7c529d64d9c3a4b41136ab03e48147e01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9e060a9b06f90318a0cc482c7a97c2c547a7e1483c14e65bb6087ca7257c15ff673f946298c57e7d90a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ee226379db83cffc681495730c11fdde79ba4c0ca0921e5a9881b361b462e86c18d8170303f37f3576c4298f951b164a3a0ffa7950a04a318f22b6185bdebef3900d7c65bcceed28c6906605406b54bd9eb07cb6a266a07a8d59ef980eed078ac8f192425c1fffbf5210a9c92a2065c40639f6421c2367b90100cae58a5a44a877dfab933564fb46b73ec4c3d9c7f068cd492e7b13a3d43cca90ce095bebe264c59a13537dd3575e47c5a87922ba687d73fbdf4cf75c5c7fae998edcc9956b64445fc973aacd815ef67bbc3ce25deb67e19207fff0d98cc0cd558a0ec9eb2bb7bee5b4e736041f80bdcb0862fbf2e9afff5e3ce0959b8fa1cfb795fe04f69cbfecdde7a927c01fe87cc89cad2e277b31e63a5619f6ffac97cb631f4ba69ce7fea3f16e3c2b15fb8b2462cbf6ef9b62b3e77173fb306f19eb12fbe2ecdedfb32acbcf3efa25d9f79838b2b76b25cec051447eab71740e862feb2fd214e4db5568ceb4a791b6bec6c1a972726641bce9fe4f68e46edf15df75e652028401e6aa448408583b00840107e57384650a4b05b90118d88301020a846765746888676f312e32302e34856c696e7578000000b19df4a2f8b5831dffffb860a4cc53efef08386da2bcdf2ccd02f5772899f7e1f3b0252b21bf309dd6f96034ee6570316f1767c75acdd7f6691589051341d1cdf1f118c5c47c505a2e48a47da6e7d26c3107799b8cf767cff1382115896c6b74f0df094690ee36d0fcecf95ef84c8401e6aa41a094904149695c8adb89cd6f020cb278275a2fd4483cfc10d7d3dab8121f69f3068401e6aa43a0cc482c7a97c2c547a7e1483c14e65bb6087ca7257c15ff673f946298c57e7d908093e10e56b7f84c8f756b3bd5422d93053db5f5a55dee436bae6d8066674e131f4f430278fc3cb1f4d9f3dd0c85410694b92887718d431d8ddf25524ece35d03501a00000000000000000000000000000000000000000000000000000000000000000880000000000000000800a9d060a9a06f90317a04eedf58a08358d43f0d37410f1c301efcc3dd738eff0b07bb4f82c83f30a0cc2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ef0274e31810c9df02f98fafde0f841f4e66a1cda04773baafa2984559c063e6b1f50e3019baae941124e89d5d7bc3f009e484a3d0a0c350e76080e62e8e4f45c1d424daec63750b940344655e81f56f0c65f1e7ab40a0cfd21dbf9df8503fb97bcd511aa04483116eb7afd0d4702532d1ff0b8e8b849eb90100002e022444181418d2d2414984070420434880e00f19494c8452044a5a7001298681544650c412916e119ca3241220808c0110050418214674422800002620a06440c08029440f8f296082ac8214002db995a0c59de7580a06168014c01036205a8ca0628e8205000458ea6110210d480a002ce0809e0410430084100d4c6420390a20a40479e91a14982410089018c4902ca40d601091081181105024a110a007904082087e211261d6008c42ceb44942602191022801165326a8aa1f8f28f8e0262c92228732026080028c8812d2057a10b884800048b10c13545b9e20f6340ab485c910af5a940909064e044f41446c6b8581653051e81603b101fc498c0b028401e6aa458408583b008385259f84650a4b08b90118d88301020a846765746888676f312e32302e34856c696e7578000000b19df4a2f8b5831dffffb86088dd96fd990be352a39175463f3902ec9f4f036ed7cd8ab3ce3f4cc70dfc8230a1a1f856e28cbc84a4ed1f95431f63cd0464f1c2f061593bfaf3eae388264d02420af41cfc0e01525f438bc3cf11b9c5a988aa6bb9c82098d567b339709ac676f84c8401e6aa43a0cc482c7a97c2c547a7e1483c14e65bb6087ca7257c15ff673f946298c57e7d908401e6aa44a04eedf58a08358d43f0d37410f1c301efcc3dd738eff0b07bb4f82c83f30a0cc2801962735bca49e800156401aa4bbe2e32d58f36cc22ce3cfd8da23ca72e10eb2f44fa1c1a1840959059d86e6f1b936457795534d45c8a554c3060e9dd39ec108001a00000000000000000000000000000000000000000000000000000000000000000880000000000000000801200221400000000000000000000000000000000000000002a140000000000000000000000000000000000000000").to_vec(); + let any: Any = header.try_into().unwrap(); + let err = Header::try_from(any).unwrap_err(); match err { - Error::MissingTrustedCurrentValidators(t) => { - assert_eq!(t, height.revision_height()); + Error::UnexpectedTurnLength(turn_length) => { + assert_eq!(turn_length, 0) } - _ => unreachable!("err {:?}", err), + _ => unreachable!("unexpected "), } - - // untrusted validator - let trusted_validators = &to_validator_set([5u8; 32]); - let err = verify_validator_set_non_neighboring_epoch( - &cs, - height, - trusted_height, - trusted_validators, - next_validators, - ) - .unwrap_err(); - match err { - Error::UnexpectedCurrentValidatorsHash(t, h, hash, cons_hash) => { - assert_eq!(t, trusted_height); - assert_eq!(h, height); - assert_eq!(hash, trusted_validators.hash); - assert_eq!(cons_hash, cons_hash); - } - _ => unreachable!("err {:?}", err), - } - } - - #[test] - fn test_is_non_neighboring_epoch() { - let mut h = Header { - account_proof: vec![], - headers: ETHHeaders { - target: header_31297201(), - all: vec![], - }, - trusted_height: new_height(0, 0), - previous_validators: vec![].into(), - current_validators: vec![].into(), - }; - - // not epoch - let base = 31297200; - h.trusted_height = new_height(0, base); - assert!(!h.is_non_neighboring_epoch()); - h.trusted_height = new_height(0, base - BLOCKS_PER_EPOCH); - assert!(!h.is_non_neighboring_epoch()); - h.trusted_height = new_height(0, base - BLOCKS_PER_EPOCH - 1); - assert!(!h.is_non_neighboring_epoch()); - - // epoch - h.headers.target.number = 31297200; - h.trusted_height = new_height(0, base); - assert!(!h.is_non_neighboring_epoch()); - h.trusted_height = new_height(0, base - BLOCKS_PER_EPOCH); - assert!(!h.is_non_neighboring_epoch()); - h.trusted_height = new_height(0, base - BLOCKS_PER_EPOCH - 1); - assert!(h.is_non_neighboring_epoch()); } } diff --git a/light-client/src/header/testdata.rs b/light-client/src/header/testdata.rs deleted file mode 100644 index a29e948..0000000 --- a/light-client/src/header/testdata.rs +++ /dev/null @@ -1,564 +0,0 @@ -use hex_literal::hex; - -use crate::header::eth_header::ETHHeader; - -use crate::misc::{ChainId, Validators}; - -pub fn mainnet() -> ChainId { - ChainId::new(56) -} - -pub fn validators_in_31297000() -> Validators { - vec![ - vec![hex!("0bac492386862ad3df4b666bc096b0505bb694da").to_vec(), hex!("b0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e").to_vec()].concat(), - vec![hex!("295e26495cef6f69dfa69911d9d8e4f3bbadb89b").to_vec(), hex!("977cf58294f7239d515e15b24cfeb82494056cf691eaf729b165f32c9757c429dba5051155903067e56ebe3698678e91").to_vec()].concat(), - vec![hex!("2d4c407bbe49438ed859fe965b140dcf1aab71a9").to_vec(), hex!("93c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab0").to_vec()].concat(), - vec![hex!("3f349bbafec1551819b8be1efea2fc46ca749aa1").to_vec(), hex!("84248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a").to_vec()].concat(), - vec![hex!("61dd481a114a2e761c554b641742c973867899d3").to_vec(), hex!("8a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d25").to_vec()].concat(), - vec![hex!("70f657164e5b75689b64b7fd1fa275f334f28e18").to_vec(), hex!("96a26afa1295da81418593bd12814463d9f6e45c36a0e47eb4cd3e5b6af29c41e2a3a5636430155a466e216585af3ba7").to_vec()].concat(), - vec![hex!("72b61c6014342d914470ec7ac2975be345796c2b").to_vec(), hex!("81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a51").to_vec()].concat(), - vec![hex!("7ae2f5b9e386cd1b50a4550696d957cb4900f03a").to_vec(), hex!("b84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e").to_vec()].concat(), - vec![hex!("8b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73").to_vec(), hex!("a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d78869485").to_vec()].concat(), - vec![hex!("9f8ccdafcc39f3c7d6ebf637c9151673cbc36b88").to_vec(), hex!("8819ec5ec3e97e1f03bbb4bb6055c7a5feac8f4f259df58349a32bb5cb377e2cb1f362b77f1dd398cfd3e9dba46138c3").to_vec()].concat(), - vec![hex!("a6f79b60359f141df90a0c745125b131caaffd12").to_vec(), hex!("b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b741").to_vec()].concat(), - vec![hex!("b218c5d6af1f979ac42bc68d98a5a0d796c6ab01").to_vec(), hex!("b659ad0fbd9f515893fdd740b29ba0772dbde9b4635921dd91bd2963a0fc855e31f6338f45b211c4e9dedb7f2eb09de7").to_vec()].concat(), - vec![hex!("b4dd66d7c2c7e57f628210187192fb89d4b99dd4").to_vec(), hex!("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").to_vec()].concat(), - vec![hex!("cc8e6d00c17eb431350c6c50d8b8f05176b90b11").to_vec(), hex!("b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a419").to_vec()].concat(), - vec![hex!("ce2fd7544e0b2cc94692d4a704debef7bcb61328").to_vec(), hex!("b64abe25614c9cfd32e456b4d521f29c8357f4af4606978296c9be93494072ac05fa86e3d27cc8d66e65000f8ba33fbb").to_vec()].concat(), - vec![hex!("d1d6bf74282782b0b3eb1413c901d6ecf02e8e28").to_vec(), hex!("939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce739").to_vec()].concat(), - vec![hex!("d93dbfb27e027f5e9e6da52b9e1c413ce35adc11").to_vec(), hex!("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").to_vec()].concat(), - vec![hex!("e2d3a739effcd3a99387d015e260eefac72ebea1").to_vec(), hex!("956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d21").to_vec()].concat(), - vec![hex!("e9ae3261a475a27bb1028f140bc2a7c843318afd").to_vec(), hex!("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").to_vec()].concat(), - vec![hex!("ea0a6e3c511bbd10f4519ece37dc24887e11b55d").to_vec(), hex!("b2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c192183").to_vec()].concat(), - vec![hex!("ef0274e31810c9df02f98fafde0f841f4e66a1cd").to_vec(), hex!("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").to_vec()].concat(), - ] -} - -pub fn header_31297221() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8ec5&boolean=false - //https://bscscan.com/block/31297221 - ETHHeader { - parent_hash: hex!("da01d8fede81f2840ea4bd2d5586d4303f68c73becf0a23d1d6dddd4890bd274").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("ea0a6e3c511bbd10f4519ece37dc24887e11b55d").into(), - root: hex!("97528e3167d013309f8585c8db78f4af02b0acbcf92e6b3aac530f9972b18ded"), - tx_hash: hex!("ed65d042cdbf107e3803eb2aaa1932b1ae28ab8b2fc4df9bafb9217b390aa9c9").into(), - receipt_hash: hex!("b8394040a65867ce80c2f4fd34d3bba3095b80ff9ccaea1e58669ca564a1e103").into(), - bloom: hex!("91a876410d0c7012c91502d6845200a6d208a629cdcc06a0053861b2b9760ba2c8293640420712c5329374810216e098cfeba05d250267e0d8421025952c6a30242ee00309c60244e5338ccbca3104be2518206551e6580b0c5d81b0c8a33c05e02cb13e7b22c3cb248d041493691c51087c8acb1b0bb68e884ec552e443b4041e0b07914679c2eb02f4240458036fae4aa6fe9dd421313b75513b74aa505c30067648177ea9d9c2332d5deebe9f38d046eac9840301613312c0252a7813aaf8ee39440e3088e446cc5d0a9e1ca2fb00a0c8b1421d1dc03611ba406a2a34e5fd16399c1d89dec60741b05462e1110945781a845e7db1796c9bca3e909b61205d").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8ec5", 16).unwrap(), - gas_limit: u64::from_str_radix("8583b00", 16).unwrap(), - gas_used: u64::from_str_radix("aa7b54", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0d4", 16).unwrap(), - extra_data: hex!("d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a2f8b5830ddfffb860b4de956fe39e1e7e6b535f75054f2efea8ac185ac2b76384c749cc45f7decfea9999b9b3b41e5666e36408069cdd06870e266fe868b9128ce0a0aecf4ecc6b0e42d10c5e646e9571a862dee7112e88f39ddc476b67be9cf32ccb337d3496f901f84c8401dd8ec3a035be0876c21a5a5726193d1adb8ce9ebb6eb95757407cafb9106a57f0d3d12228401dd8ec4a0da01d8fede81f2840ea4bd2d5586d4303f68c73becf0a23d1d6dddd4890bd27480939d982a7958bf5912c1105da4673d035df33b685ad798e6f589ada1b40f63fa27edbbcea731e17928a54c07847a70d7e262a0bc41e68e5fcda124a37f4340b301").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("0b89f31647758aaffb46d3a71f2bcee82816fd1a8c25dbddc774bd14524ae379"), - } -} - -pub fn header_31297220() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8ec4&boolean=false - //https://bscscan.com/block/31297220 - ETHHeader { - parent_hash: hex!("35be0876c21a5a5726193d1adb8ce9ebb6eb95757407cafb9106a57f0d3d1222").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("d93dbfb27e027f5e9e6da52b9e1c413ce35adc11").into(), - root: hex!("1283c0ddaf635ba45c04c7dcd3ee83370027d55fee45e9bd2a8f121074808ece"), - tx_hash: hex!("62c9236c31a88ecf2d5ecb4666f06b78fad90bc6cde486714c92ac123b26e56b").into(), - receipt_hash: hex!("babb28a01a3e0fe3657bd296123c54e8e6368588e943ab3b966d97effdcc1ae2").into(), - bloom: hex!("dd6dd27f6ff5373d2ef7e4edba7714d6f3daf37bd7d8bfffba5fd73b32befff7ffc75fcbfbb955cfeab33ff77d1fd0b7fbd3d1fc05f5f02f7faf3efff3ed7afcffcffbf65d52ad3c9b75cedcb8d672fafdb1ffbf52f7af38e2fce0bffa6b0e3f5ffd7dfeaf4fcd630acd8ffc917b3dbf0ca36c63784d76b65eead7b9f6ef1fbf5aafff6e2e5fba9ff4ffbd57eeebdcbe76f67db77c36bdc86dabb3d3bccbdead97e726e3ebbefbf6effef7efcffebec3f7afcfef4ebaf9b5f7eaf77e6f5bebebe5e7f59ea35efbf7f6ea5d2fc36ffdeeadffb5eec3ba5e3dbbd774cef627f77ff1bafa3dbdf3d9de2735e7c685a723b6fc3e27fb767d7179bf2ffadfb9b9d8fb").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8ec4", 16).unwrap(), - gas_limit: u64::from_str_radix("85832a7", 16).unwrap(), - gas_used: u64::from_str_radix("142a9ef", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0d1", 16).unwrap(), - extra_data: hex!("d88301020a846765746888676f312e32302e34856c696e7578000000b19df4a2f8b5830ddfffb860a4332ba47e6728f4b0e52e490cf4bd3cc4fc742c12bb8a8e5912095c71d9c845f5ddc5fdd4128dbed0e1bcaf4da8236b05ded0aa4a4c81f4a4fb2250f790fe1b21edb1aed0bc7bb7d4a78b26c6dd9af3b65a2bacb5b44e4a7b1dc3284e9d7d6bf84c8401dd8ec2a00f0fc4bae073bbeae37d8ff5395c95480fe5a9149bad4f0cd4f5e8e32d18b32e8401dd8ec3a035be0876c21a5a5726193d1adb8ce9ebb6eb95757407cafb9106a57f0d3d1222805bd7bc1a83768b5c7a505eed50eca8fdddd8a583a46d37f80a2d714be9f8ca2b04b0ba1398956512d18b30e3a56755245df898b98f8d5f6131eb7527f7dc65b101").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("da01d8fede81f2840ea4bd2d5586d4303f68c73becf0a23d1d6dddd4890bd274"), - } -} - -pub fn header_31297219() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8ec3&boolean=false - //https://bscscan.com/block/31297219 - ETHHeader { - parent_hash: hex!("0f0fc4bae073bbeae37d8ff5395c95480fe5a9149bad4f0cd4f5e8e32d18b32e").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("d1d6bf74282782b0b3eb1413c901d6ecf02e8e28").into(), - root: hex!("a6923c4f9bce5b7cc15a16d85222ce2618aa0f12bca0fa6b703d9aa5aa412648"), - tx_hash: hex!("57dc9bdab942a85992bf2bb645594c35d9aa1df083fee8207df409886d313d6d").into(), - receipt_hash: hex!("3bfa2879642e0273e765670993bff0ec2f22e589317782599cc6b79453441096").into(), - bloom: hex!("eea73ff54e3fd7191d7f53f49ca3c29eb5b9688d0fafc2d33e7ee12d3a35cc69ef7ebd97cfc31b177a6b73ccda3622f8f9b6d95b59976d306e3ecc5f7431eed49e5cd9f70ff7cd29df7de1ebfd3bae347bbd98a770559ede746e6f93c9fb4e23eb3db0a53e57bf4eb77d7c36d3f37944cd99ddd55bb79f7e1d57f5b7ee1b6eeaf987c3a4da37134c5fa5be1fd2107bce442ea68f7c34fc9f6beba6df46fb78e63fd7323f57c723718edfddce9bd9fd425a978f65a7bed42fff41f666aefb58f76dd3ff561332ffaeb7fac28d55e99b7cf1f7b1a768b7a8bcc13e7ce715f4affed53eb4e4b1c177bd5f5d2de36bf39bd6b8d6976e5dec7cccb4f4fd932a677ecd").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8ec3", 16).unwrap(), - gas_limit: u64::from_str_radix("84fe2c6", 16).unwrap(), - gas_used: u64::from_str_radix("f43a7c", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0ce", 16).unwrap(), - extra_data: hex!("d88301020a846765746888676f312e32302e35856c696e7578000000b19df4a2f8b58305dfffb860b7ab6f15df58e54befa47c75d64d32161823c59edf5bade334b55623eceb68b45752b058206ab7805f277362b7df153601ff6c28a4359f22a74b39304f929af5ca3192f58af57955bd33002402c6824834448ac33fb34d702d2e0d08d2bdcb8cf84c8401dd8ec1a0a493bd047c4c05912239fccde0dbd49730ec916afaabff66abd2e4d8bb351a938401dd8ec2a00f0fc4bae073bbeae37d8ff5395c95480fe5a9149bad4f0cd4f5e8e32d18b32e80515ed762f28c37e88f3d4f21bb33aa5fbd548f3bd168a4b4eeba9ed4c128f79f16886350f86283a571bd58d56cbe2ede5500d4261f8536677c4f24fd5542db0a00").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("35be0876c21a5a5726193d1adb8ce9ebb6eb95757407cafb9106a57f0d3d1222"), - } -} - -pub fn header_31297218() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8ec2&boolean=false - //https://bscscan.com/block/31297218 - ETHHeader { - parent_hash: hex!("a493bd047c4c05912239fccde0dbd49730ec916afaabff66abd2e4d8bb351a93").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("cc8e6d00c17eb431350c6c50d8b8f05176b90b11").into(), - root: hex!("b111fd4d787edd2a9a54e9e76aabac9bedf7213ddcf44b9960f334c9303b0256"), - tx_hash: hex!("c81295cf7fdfa201ef13477519a25fd0749c8085acc05f59386291fb87fac10b").into(), - receipt_hash: hex!("6024c6edc9ef851420121f565972736a182e40a2c5603c40de6afa8c1848b83b").into(), - bloom: hex!("66a0839004a3501048881050821442000900040000814969480300289840012088035a00108000010a8810000142020081618811240001212020801000201a0404140848034000200106100898884434249023000244010020441200808006000a0b20201a0200182402005810002a401800c80c007e36260000401083c8041c0020c39684308058138424001c0010002824a40524a0100810081440184028a0a2d8180110814006022c40083b1001004000a010400200043001192823100044932045028012804600700820a92612402820010000040838011451d20800a4250838080102003100032184089002111440200b0426a050480010300000011001").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8ec2", 16).unwrap(), - gas_limit: u64::from_str_radix("8583b00", 16).unwrap(), - gas_used: u64::from_str_radix("35a2f2", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0cb", 16).unwrap(), - extra_data: hex!("d98301020a846765746889676f312e31392e3131856c696e75780000b19df4a2f8b58305dfffb860afc7a23949201ffc50f92c39cb6a3a42f960edd1cafc424b852f511da8dbc052c0bb0222baa6b3a560cfe41a5a7b95c709c11e05b6471366ddb49ba73d0a547b085851d45b51dfbff2cc71f2ca93ff0d6402ecf1c534f240e4b67dfec13efc38f84c8401dd8ec0a03f20b11009e964211f4ef2e316ddf214066d6e0603b6fa2a283b14133c0aeb1b8401dd8ec1a0a493bd047c4c05912239fccde0dbd49730ec916afaabff66abd2e4d8bb351a9380740b7c6a2a1f2f5083f10dc247ed6e6223edd986368179556bd9dd3d78949149357dd8ed2793a0c701d6b7df744261439b71ef4cd2ef9b189afcc2f8105745ac01").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("0f0fc4bae073bbeae37d8ff5395c95480fe5a9149bad4f0cd4f5e8e32d18b32e"), - } -} - -pub fn header_31297217() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8ec1&boolean=false - //https://bscscan.com/block/31297217 - ETHHeader { - parent_hash: hex!("3f20b11009e964211f4ef2e316ddf214066d6e0603b6fa2a283b14133c0aeb1b").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("35ebb5849518aff370ca25e19e1072cc1a9fabca").into(), - root: hex!("158af1b358e1ab7c08fd65a742d3e36c372859047aa6d1f8b47f8c6ca1a21d13"), - tx_hash: hex!("2e308aa7adf3de39000a56dfd3596435e357304504b9ecb1401492dcc101cf88").into(), - receipt_hash: hex!("698a86c1d0922df0705634891cbc82347d693ecd9e6ec0201ac9b9ffb4006cca").into(), - bloom: hex!("14244b5f06401457d30562ee82512903900dd1291845c7203f3f49517c14a7b08eeb1643764ed0295a328daf585e442a87c0dc3eef1ab1195200248805275b88847ad90a0f564c1a133a621dd3ed006af41494d545467e5bb5bc80f9b4492d36ce2c12a7aa064353340d18a5c11659c04904a952bb45fd06a344ee50cb4db65090eaa19787bd929d10bf6608d508b19b24651ec5f916309b31b68cf88841c8becf098432529e06423a2e83edae3fb40226ea99652ac09398fa626db2f116c4c8a47057b20a81292e13d0ee6674a0d92221d50e6a8126ea1d835fdbdab2b8fc2e9cb0ced009a6e37d29d5a842f5018932486c87294162fae82017883c5e6960c4").into(), - difficulty: 1, - number: u64::from_str_radix("1dd8ec1", 16).unwrap(), - gas_limit: u64::from_str_radix("8582a4f", 16).unwrap(), - gas_used: u64::from_str_radix("d5aba3", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0c8", 16).unwrap(), - extra_data: hex!("d883010209846765746888676f312e32302e36856c696e7578000000b19df4a2f8b58305dfffb860887daa937dc51ef1bdc88a3f2e52f51ccc297a3439741cf23e3bc635ecca60413c070e136840b09112b15158b54887801215cd8e3354c552e03587b922c8aa3c444c55336eaefafbf88708863869316136f0a68e45d62c243eb5976dffe41656f84c8401dd8ebfa0d1cbcb756aa78425abb3fd8eb10e814c67b8cf6e7750458b8c597388bd8682928401dd8ec0a03f20b11009e964211f4ef2e316ddf214066d6e0603b6fa2a283b14133c0aeb1b80b2c9b0fdb99e7bf632bdb2ab30550cff337b15c9163fddc47c9cc20b9582c71343857e79a7dae2b38715d8cbecf111a2d1cfcfbad8f4b65abd6b67ad2eb97bb900").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("a493bd047c4c05912239fccde0dbd49730ec916afaabff66abd2e4d8bb351a93"), - } -} - -pub fn header_31297216() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8ec0&boolean=false - //https://bscscan.com/block/31297216 - ETHHeader { - parent_hash: hex!("d1cbcb756aa78425abb3fd8eb10e814c67b8cf6e7750458b8c597388bd868292").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("b4dd66d7c2c7e57f628210187192fb89d4b99dd4").into(), - root: hex!("57ede97b62b05af1187766de108267b2f27537ed9edd1a9f7889529db4cca965"), - tx_hash: hex!("93775f7dad7f0678386501fd9419fbff9e902707687c7baa4c73478a74c4e839").into(), - receipt_hash: hex!("0e3fb454aa5489134df6457875bfde27c8eb43f092cf84cffb1f007d8acbe1fe").into(), - bloom: hex!("882cc625e0381010c60011c584004440a00b1121012c82100038612a16088082af04b07e28049011662125b1020680b08300148849480620d8262c280a640a081d7485d2514625203328e09802204128703622a52054820e002d0000c8148445c20908222a1605012229022681101ae2081010175041848624510818de623640110a2901466d5882229d258e1921042a8924158511203a8800c8c0508980102092050022078d1402270638cd3f0a1640cc058d0108128189308365a020c224d8242c1ce290c361864190899b1a0012542500061006104094031347462a02e424281808521004114021881c484c0041295950e26951e09448a002419000413b06").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8ec0", 16).unwrap(), - gas_limit: u64::from_str_radix("84fda76", 16).unwrap(), - gas_used: u64::from_str_radix("847ded", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0c4", 16).unwrap(), - extra_data: hex!("d98301020a846765746889676f312e31392e3131856c696e75780000b19df4a2f8b5830ddfffb860b01dbdb421b9fb5b1f71f196b5e1a8979b353ebfb25bf1a0ef31cc692139df7918b4d2db38211f91ee023bbdf78ac50b00d1497f7d90e42adb7826b21c129d5c706219f37d9216b27be379a4f2854149fa744ef734e8558070c5e8c4fd794c5df84c8401dd8ebea017148d821da270f09540075131924b934bc0352dd71d8b8f60274f39d73231dd8401dd8ebfa0d1cbcb756aa78425abb3fd8eb10e814c67b8cf6e7750458b8c597388bd868292808cc4af67170aaa12f7d2c44f6bec754eadaad71cf12df86ad87667fb2a9579940c3a579e4b5bb1c63c02b488429d683c9e3599b0583f0e4015e98d674f58281f00").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("3f20b11009e964211f4ef2e316ddf214066d6e0603b6fa2a283b14133c0aeb1b"), - } -} - -pub fn header_31297215() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8ebf&boolean=false - //https://bscscan.com/block/31297215 - ETHHeader { - parent_hash: hex!("17148d821da270f09540075131924b934bc0352dd71d8b8f60274f39d73231dd").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("b218c5d6af1f979ac42bc68d98a5a0d796c6ab01").into(), - root: hex!("a6e3d060b775a05eaa251583fb248df682fa839bd575d254eb4330d6c92f0356"), - tx_hash: hex!("4a81457bed752a8611a3fcf1409e6bfc34c8006651f64e6fdb5530a113d8972c").into(), - receipt_hash: hex!("a8539e4e87b5ce8ee15a3f9c52113062de8883c1ea062255959e3f3f5350ec00").into(), - bloom: hex!("1177e6c48819553fcb1800dcc612126e24206a13cd4d054bea0a07b81f00a03e8e43f8c2c280905102227a9355da28c18e1c000a071c61a140352328113d228007d640114bd00c69db01a449c835706ca8dcab8040744802234e841088042eb42a9d23365e262a370c0d001693eafc4348a6a440294fdf23010ac910944b6df8888ec3142b5440dc30aa5500a894fc9bf0b646857e6838de318cd1c300929c20828da412533ae674b610cb1e6f85e54008a4d7d0878286a57469a3b57752a2e7b38f14828276a80e30ab1c48f23650e0b41447e5c14f0417819e7d87833cefab519990032ef8e7274125026a8163152c278085a9d078c67c23b87d00da15f00b").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8ebf", 16).unwrap(), - gas_limit: u64::from_str_radix("84792e5", 16).unwrap(), - gas_used: u64::from_str_radix("aac551", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0c1", 16).unwrap(), - extra_data: hex!("d88301020a846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5830ddfffb860b9b1a84b0ce0243a5b8592ffc6562f1f9f6e95197a1ca1ea17eb300b4f101382aff91466a179e5b9ad4fa3423f6ed40f14edef5a8addd5590754049e9828001b3aa9e355abd098b01b059781512654f9dce636865e6dd98c9c41066e09f64af2f84c8401dd8ebda0e5ec815463a14fc0a652302d302e93c2a06280d115782a183f5378692e8638288401dd8ebea017148d821da270f09540075131924b934bc0352dd71d8b8f60274f39d73231dd80615eb294cc6f3c9f5a307dca23199a3844bf63b9078c41d457d7732a7956189a4b68c910d5ed0eb7fe4e7432061ab9ca6bccc150099a5ad554112aa34494cc6801").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("d1cbcb756aa78425abb3fd8eb10e814c67b8cf6e7750458b8c597388bd868292"), - } -} - -pub fn header_31297214() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8ebe&boolean=false - //https://bscscan.com/block/31297214 - ETHHeader { - parent_hash: hex!("e5ec815463a14fc0a652302d302e93c2a06280d115782a183f5378692e863828").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("a6f79b60359f141df90a0c745125b131caaffd12").into(), - root: hex!("46c90c2a67cf640eaf1c7e9b627bf137df627a4aa602c7c42cad02e6b3aa61ae"), - tx_hash: hex!("348bee6e3ed5a24936ef58c39a5656f7390ccf15023f76c902385bb37b88ae73").into(), - receipt_hash: hex!("5c64f76cfd4aae1954bc309191547a6bc7a3fc3811867a9d0501d4c49e37f7d7").into(), - bloom: hex!("30a757670ff6b7b08a55e045b7df00da267969e3bea749623a324fbb1fde51d39c565fc3c881c27d7e945e09565a63e3c39c4cd9643a24855c28269ae0f0e0e1f67db0e995680de41f71155b8a7ca0a9e89e9cac436d8189d56790628f81640d2fdf596efaaa124fbe2bb75a232bbda10ae0ca31349b7f643302c97a8cd106e7944d79ae139d6bf0bdcd5fda4cee1b8bcde6a5917911f1a8bc7198d4c4fa0cf98adaf037da23ab21b64edbceabef154056af8de4499885a157a261a0218261ae78983ed32186ec7e7692dc3b761271a22853094b0d35a8b78d30570a46a1e528923c9ce10182f1061b1d6ca3e20ba15067e6aff726fd7a4aabbc3e883c754dd0").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8ebe", 16).unwrap(), - gas_limit: u64::from_str_radix("84fe2c6", 16).unwrap(), - gas_used: u64::from_str_radix("a0a9fc", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0be", 16).unwrap(), - extra_data: hex!("d88301020a846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5830ddfffb860b6b6980dabc6fb7a8e6563155150083f04f73a6a2ea6532eea4bb56ed5ac2178e20c27d0d4dac3e8852cc79c87de3c1d174a26ad0ef211e4e948881ef0c5dbe49cdb3919997e42f79f126ccc0fa879eb750db937033427666fbf8dc5f29e0b81f84c8401dd8ebca0c74fda0e42d712edb445971bc504af27873c62f5f8dc7392f0e04a07026cff188401dd8ebda0e5ec815463a14fc0a652302d302e93c2a06280d115782a183f5378692e8638288098360d498a03e2a7f8452086e83fe23b3fabbd623ddd30369811af6f592b54c520675d0e73882204d5b97bf391fab38af5ee0d58cd1b2f60869a370e3c4c5c5600").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("17148d821da270f09540075131924b934bc0352dd71d8b8f60274f39d73231dd"), - } -} - -pub fn header_31297213() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8ebd&boolean=false - //https://bscscan.com/block/31297213 - ETHHeader { - parent_hash: hex!("c74fda0e42d712edb445971bc504af27873c62f5f8dc7392f0e04a07026cff18").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("8b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73").into(), - root: hex!("d7dc8b11d03723bc786b44fbd36ef47ef34471e1b7020f6d60a9239d44a5e4c8"), - tx_hash: hex!("90d350b4228b27f146ba9917abb86c867b6846ee277f38daa2fe908cdc8450f2").into(), - receipt_hash: hex!("23f67e6e9fa18049ca3a8d2984d1ccaa6d020b9d6ed37e72bdbbe6c81ff0f5fc").into(), - bloom: hex!("ad6ed6550e5cb77aa96db8f5eeabeed6f08bd2cf97cc48f8a3fa63eb5e89895aff4c1953f649d52773a33ae7f75ffe82dfd28ed945bd782f237fee1f9c6c6b9c8e54d4fe2d534c3b95f9ee8d8e1c22bf63b4e9a6d0e7ecd8effe51da8a2d2e31cbbf2a7e7b3fac29b4cd3d16dfdafbdd7acfacd3baadf58b7e47879ff04acecfcecf7da7e67589c9b6bf77901c875b1d5a769ec77e68fe9f755931cc907794e99a4c27e37bf6b7526f6eb65edb9f7ec2c0e6ada9438bd5ef3feb25a37df6b9f5a8ef7dd398430b6712f85f66b3741aeffde7d763c45b4ebcadbff5f6f23ce776f1fdfefb37f4d53fdb2537da5fe5cb77bee77ff59b3c7dfdfde3ff9c78e94ade").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8ebd", 16).unwrap(), - gas_limit: u64::from_str_radix("8583b00", 16).unwrap(), - gas_used: u64::from_str_radix("12d7505", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0bb", 16).unwrap(), - extra_data: hex!("d883010209846765746888676f312e32302e36856c696e7578000000b19df4a2f8b5830ddfffb860a7977214b4091a4d9b36b958bae429233d1c122d2c691f4cd9f34768b72b1cc391a23d5d7752d06177d6f870e32ff3f41553ac2e4e16c44adb75bf0f78894bed963b77213057866a75954538741a296446cff7d19c68123c8b710252bdf52c73f84c8401dd8ebba096014f0baf3bd1f8096f66e7ee026238ac2e2d199c00e2bf2cc5c0183ab47c4b8401dd8ebca0c74fda0e42d712edb445971bc504af27873c62f5f8dc7392f0e04a07026cff188021b063740fb3c1e3a639e7a4ce20a7b58abcc5718a1c8e78677eb75f1e4f86a514fbc225bbb3229f7b8dbc26de24eedf456f1184bd67418582270fe25dccc09b00").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("e5ec815463a14fc0a652302d302e93c2a06280d115782a183f5378692e863828"), - } -} - -pub fn header_31297212() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8ebc&boolean=false - //https://bscscan.com/block/31297212 - ETHHeader { - parent_hash: hex!("96014f0baf3bd1f8096f66e7ee026238ac2e2d199c00e2bf2cc5c0183ab47c4b").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("ee226379db83cffc681495730c11fdde79ba4c0c").into(), - root: hex!("375f3881abfe517cfef67f6fa4e4e6a6cdd55f59daba5bf549e42cf0f0bae4b9"), - tx_hash: hex!("cad310793c8d7a169ebb1f0bf1499829af25ff43a96620bcf8e4eaad746d09eb").into(), - receipt_hash: hex!("5f33ebd5da8fc4a50aad629c197df5ad9fa11b386856d7eca9e7198c3fbd8cfe").into(), - bloom: hex!("0020630015319710008002d788aa0006e509288314201202106a2105bd045316ea6050784001b60422282e8a0107c10081543311500c20b101900009d0e000900547848a555c0828250153880440a031b4134cc90c61cf08082c0a0084100660480a24343e6609090665c81083080873a884d47a860fce524101281480ca08988448aac0204003d7069a042320028080016e852d713a640c118059400d921c692a008826018046102200d24402a006204a0294040a0484e3d1a025f04b8187640122d507809022020004884157327008ac08030680202612451c44e30605a52d651050452804662b411c06a0016203a020040c2419284448a06155088081610d").into(), - difficulty: 1, - number: u64::from_str_radix("1dd8ebc", 16).unwrap(), - gas_limit: u64::from_str_radix("8583b00", 16).unwrap(), - gas_used: u64::from_str_radix("8dafa1", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0b8", 16).unwrap(), - extra_data: hex!("d88301020a846765746888676f312e32302e34856c696e7578000000b19df4a2f8b5830ddfffb860a3fc89fc965524cbda1745ddb014024d04182e9da19f4f508c998b2f5236d553b042dea0f061262eea3fc046799555890b7c054721eed6d48bb2e1e20e520fff107617d2002090b781d866daa35943464bfc575abacdc000ac019a642565e108f84c8401dd8ebaa0ae86b11151a6e6bc2ee0b782bc806d02049f9c50c7187ab0e398b4faf504ba188401dd8ebba096014f0baf3bd1f8096f66e7ee026238ac2e2d199c00e2bf2cc5c0183ab47c4b808e9209f39c07332b1163d586ee07e35d16ba59dfd8484e9980cc7b128c55f86374eee7f035aa2bddbc8d6a3bc7707014e6884c2f95692ee683dd3e4440feae8300").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("c74fda0e42d712edb445971bc504af27873c62f5f8dc7392f0e04a07026cff18"), - } -} - -pub fn header_31297211() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8ebb&boolean=false - //https://bscscan.com/block/31297211 - ETHHeader { - parent_hash: hex!("ae86b11151a6e6bc2ee0b782bc806d02049f9c50c7187ab0e398b4faf504ba18").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("be807dddb074639cd9fa61b47676c064fc50d62c").into(), - root: hex!("25a1b664bacf9cd2c46f9eaa16ea6b21b0eb9e186a99ef0895746e00527d2c85"), - tx_hash: hex!("8bd39094bd4ec2b55e87eafaac3c1c34a523fc68581789ed64fc7ee81f1c3a6c").into(), - receipt_hash: hex!("868924fa9b72d69921a4822b4c248bc6912d1e0b07f95733bfd4cb19f9711740").into(), - bloom: hex!("0226d26210015a9200800bc4841410020000c000010ca902200001a0041020108a81f06042001012e030290002580185ce5090181182000c201b0400146c404c6b630011b9420050211881e9022510e82170e80209e40d18040e081c82820695422d0ca20e072249310c0804212038220c00800911235600004784b88048310000184da443149c840894a50e003301c8052624c1ec0100ca440600c8810854ad0212c002761c2222b124760c0e09240245380908578808004528916d5002a0b40824160318060b16308298c0403bf96420c30264000940376b7a4042221ce130903aa02810504100091114c2010859040890f22600204242a042011019110b43").into(), - difficulty: 1, - number: u64::from_str_radix("1dd8ebb", 16).unwrap(), - gas_limit: u64::from_str_radix("8583b00", 16).unwrap(), - gas_used: u64::from_str_radix("6da01d", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0b5", 16).unwrap(), - extra_data: hex!("d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a2f8b5830aefffb860b2cd9aa09d1b6e9812ab9f8135e8f1d4cb19aec1caad116b5f3e9e2c9f8b8c6491b0440640fbaa8e560c933d34726e090fc5b2958f86ccd547b9edb5b1e7a628e8176bf3eaab5126e4eee4876c1f8fac77ab421906cb31cbdbdd3aee7ca2647cf84c8401dd8eb9a0cb51a23528c482caed2ead54edafc305f0b9ee8b6bd579a266433e28e857d09a8401dd8ebaa0ae86b11151a6e6bc2ee0b782bc806d02049f9c50c7187ab0e398b4faf504ba18802db553b0ae5d2fd84035d0054004e044ac57424d7b3e10a696c914b563c1c65c702608d9eca7410647cdab23741cedb277efd52d151f0db53e88d8e7f21ac70100").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("96014f0baf3bd1f8096f66e7ee026238ac2e2d199c00e2bf2cc5c0183ab47c4b"), - } -} - -pub fn header_31297210() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8eba&boolean=false - //https://bscscan.com/block/31297210 - ETHHeader { - parent_hash: hex!("cb51a23528c482caed2ead54edafc305f0b9ee8b6bd579a266433e28e857d09a").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("7ae2f5b9e386cd1b50a4550696d957cb4900f03a").into(), - root: hex!("5d69f7ab2b1c76fbdbe2cf91ed2b2d515ab9e4e614f12377a29bd7cd16536481"), - tx_hash: hex!("d3d9091b8812a471b890629fc2dc64dbc5756c054e50b77dc41f9c59c35428f5").into(), - receipt_hash: hex!("6522a3bf645304f5698c92f770c022b735b08c97113cc2384c888d8a1bb5ed15").into(), - bloom: hex!("10a0926ca4b13410082800458641a0861014400700804248c4444dd012403411cf4090a044069000da2434209216d8c85b87e818010a622020000000c07002592452cc6e9341952ab1320789a82659bb333e812007400a902647003d818002e9206c233c0a428028241b008209428b69080048511452ef8f8002409457d801008c8aa1940238010ad0e115200c14188c79f6a687a88294a9ab0082400a1b04bd421ac060568303e4400a49440e043910a690840068608024408a49e01280138420093f4608a02986d0d012bd380210a2a0506242480480d53350c9820280a000503cb80c00403b91253914a0e90205c04560a6188a08626000133d4017c83491").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8eba", 16).unwrap(), - gas_limit: u64::from_str_radix("85832a7", 16).unwrap(), - gas_used: u64::from_str_radix("6bf9c2", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0b2", 16).unwrap(), - extra_data: hex!("d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a2f8b5830aefffb860b81cf27049e5890b663de5dc314505ab868cfceb20ec851a3e537af30569f8c49f591367b8c5174e459a56a0d9e85fde0d1866d9e03c7d07474020208077c83fd57067f8eb2c4b0522492dfc7d49ab5a769b54649f7e3832304778500d0b9b4ef84c8401dd8eb8a077545edd1aa19c89e81b0a1360ab862aab49c6193a18a52ec22f5922c56a17b68401dd8eb9a0cb51a23528c482caed2ead54edafc305f0b9ee8b6bd579a266433e28e857d09a80d23e1ee55dadb773514c3c830f784738af31c5d200e7ce02c026d31bd4b6a8b00420627f3ea649ae451250d8dc9afa1f420640f24165a6cde33cb9402f58688b00").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("ae86b11151a6e6bc2ee0b782bc806d02049f9c50c7187ab0e398b4faf504ba18"), - } -} - -pub fn header_31297209() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8eb9&boolean=false - //https://bscscan.com/block/31297209 - ETHHeader { - parent_hash: hex!("77545edd1aa19c89e81b0a1360ab862aab49c6193a18a52ec22f5922c56a17b6").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("72b61c6014342d914470ec7ac2975be345796c2b").into(), - root: hex!("64b13ec7180a8d694195c275043ce997f75a544e0a19947beae10e6e994061c1"), - tx_hash: hex!("cc20a7302764361da8a1b5068c523de3f56be6c71d6f83cb27ba9c648029a6cf").into(), - receipt_hash: hex!("c6aa644b38dd0efd1238ff89a1f07dc346c4a231d5a8fe1df2eadb30ea1386d6").into(), - bloom: hex!("8aedd6798fb8f77c58254df5a5c035cb9246ca6b34b5d641e63251ebe88cb5d1badedf4fe8e1c9a9bf20ee3e65da52e0ef246de10628e671dfaee71295e622a254e3ea4b2f4c04c507f004d8da28042f21b67555c26d835ab68cd11995a532d94addecf6fa4f7245886d05ab6101e9aa7921b64ea0ef57a40d30acf7eb4f1e465cc9402f0c575b0f95f82454361f7b992bee9e97f96e82e82b2b20e83aca7de5862f9861fead7740edcd3fee5fce681e47a118f565a0795c7be6ed26e15e43da38775f4a7596196ef920a80a6172f2a2eb1f21d904f5ee170955548e0832e63d9279acfa822763113b197a576600cbf0c98c1cf9767c61f2ebaf9ed8985d799a").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8eb9", 16).unwrap(), - gas_limit: u64::from_str_radix("84fe2c6", 16).unwrap(), - gas_used: u64::from_str_radix("d94391", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0af", 16).unwrap(), - extra_data: hex!("d88301020a846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5830aefffb86083d57dd73e56f4c2e0bff865baf921a537e93264fada64e29bb5a1d40bd30536aa019783c89a15462630cbfef1bad4ea083249423996a0214a1c982441f857c45cd3fc5c056d8404a317784274aa46b52187ecbe892cdd8f56bbceb2a0962faef84c8401dd8eb7a00d16a0ad7ea094c72adfd206bfc939627a0d254bed38ebb4ef940f3cb82a68b08401dd8eb8a077545edd1aa19c89e81b0a1360ab862aab49c6193a18a52ec22f5922c56a17b6802ac5addce6b711b4030e8e2a8c7cd96d5c750821a70fb38a69547718d1dfbaf770e51cce4dc3e090c45c2082d2d457e517fabcc180172276132f637597a0affc00").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("cb51a23528c482caed2ead54edafc305f0b9ee8b6bd579a266433e28e857d09a"), - } -} - -pub fn header_31297208() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8eb8&boolean=false - //https://bscscan.com/block/31297208 - ETHHeader { - parent_hash: hex!("0d16a0ad7ea094c72adfd206bfc939627a0d254bed38ebb4ef940f3cb82a68b0").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("70f657164e5b75689b64b7fd1fa275f334f28e18").into(), - root: hex!("7aa465914e03589dcd98842483bd1a94539fa2512f4c3d60d28f34c247a51010"), - tx_hash: hex!("050d6a35f73760b00e23acc15f81e59ba332afad6346454d86e45a18801fb9e2").into(), - receipt_hash: hex!("d0dbc4ad668f41a42680484f7dfe4c6a2426387a9288d15211e307bdc06c4042").into(), - bloom: hex!("85b697030202101080019845e620d0122020e60102a040b20538cf5105800012a9049801e0829014439463084218000d5112900c4612ad0004072002013009c20460901885000081099801891030807a6034020201580e06a00cb15880030ed5a44d34682b260028c22b101c618b0c403c0428408e0194043220a4398049168220ad138e0b121a20108035000818035de0263dcd386331e92500005c102ac824a70a4433da24e2012c03af0f9e466e00c5c885c0b2a00cc9200059e8404070c8f80c34264240082696c88cb04188b06eb0600020100020142f5042031882ea2c7510858003002310211da44291282320080c0e2a0ce03c60280cc82408688c02").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8eb8", 16).unwrap(), - gas_limit: u64::from_str_radix("8583b00", 16).unwrap(), - gas_used: u64::from_str_radix("723c7f", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0ac", 16).unwrap(), - extra_data: hex!("d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a2f8b5830aefffb86081325d65523a881b1ca4bf500f9f030d2fcfa3fdb0e8a65fd8d5bad40a2f727de043a37875368cbd7e9e3573789b3fad0ea31c0f29521c4eef1a1bf63cfd4570b21493de83b47bbba1cb7b5eda6c120291a053a2463029fc8fe0fc55c798c638f84c8401dd8eb6a04edb537f71dc11604b10251c74ec65f9f5d8b7b49823a4e6b3fa635043ab066a8401dd8eb7a00d16a0ad7ea094c72adfd206bfc939627a0d254bed38ebb4ef940f3cb82a68b080faf6d5df96b30eb3f7670e25e8ca826f74d8ba9dcedbdcff2650478271b7cb1c35c7335fcfc5e3469a4e24204573d05bd5979c5d3371d762cd8951a06d31cf9601").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("77545edd1aa19c89e81b0a1360ab862aab49c6193a18a52ec22f5922c56a17b6"), - } -} - -pub fn header_31297207() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8eb7&boolean=false - //https://bscscan.com/block/31297207 - ETHHeader { - parent_hash: hex!("4edb537f71dc11604b10251c74ec65f9f5d8b7b49823a4e6b3fa635043ab066a").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("61dd481a114a2e761c554b641742c973867899d3").into(), - root: hex!("53470cabcceb59cb1791c5671c730349effe4cb1e905e59a669a992bbc0108a3"), - tx_hash: hex!("744ae570d1a8a93909fb7103ebcd6fe954e022b672b5cb9be489432c488c1ff7").into(), - receipt_hash: hex!("f169c9a2f0b634c358d264f7a07b9394f4ba0835dee24ae20af9a41f535eee4b").into(), - bloom: hex!("22200260065295f9805a3140ec14002bd420c70084001e84a22a050291381010c2021140408010000631242a001e3010a2a4c00c1418a5210306289863a422f01c41962081408c008bb200a8a00839b8221016a101628002602c1840a0300e218a4c002a1a035c012e534064d4080f3b8b50ac35005b5e02c901a812a00040514881390412f0f8d0009445770ac2448e563615036910001829c000c18ac24c280382a0306380cb13c280c6070fc4940860a0dc4100c9a02378208460611002e06806150624101847105208070031b760248332c7c2140254859050c30c00ec04119094078d21c18003079442a14001240c00202a28a8ec48010704009c214120").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8eb7", 16).unwrap(), - gas_limit: u64::from_str_radix("8583b00", 16).unwrap(), - gas_used: u64::from_str_radix("683daa", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0a9", 16).unwrap(), - extra_data: hex!("d88301020a846765746888676f312e32302e36856c696e7578000000b19df4a2f8b5830aefffb8608968a3375fc9df9fe293c2b1b932f2c6c373c16c6a8ad803653c4b2e37d36954ae620e82ca7ddf800afcf43d2152ae0f03c242b5afb6917cdd19076363647ae7b62841d196f0c75084ceb616db03de5f57e06a83e743a7c4f7d3ba9ca73614a8f84c8401dd8eb5a0194822ef17f86aa711f97387a2fed416227806f12a957715630f25a0a06042818401dd8eb6a04edb537f71dc11604b10251c74ec65f9f5d8b7b49823a4e6b3fa635043ab066a806bb80e19c89b75c476fdd6d654c9391e3699257bff38af792b757842bfeae34f5e2af403ee3017fd6d774509b782b80dec4a343f47048b788e8868e80d778a6200").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("0d16a0ad7ea094c72adfd206bfc939627a0d254bed38ebb4ef940f3cb82a68b0"), - } -} - -pub fn header_31297206() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8eb6&boolean=false - //https://bscscan.com/block/31297206 - ETHHeader { - parent_hash: hex!("194822ef17f86aa711f97387a2fed416227806f12a957715630f25a0a0604281").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("3f349bbafec1551819b8be1efea2fc46ca749aa1").into(), - root: hex!("bbc943551df90ecb01b15f521ccbd5780063c41f6273689690415206d6683a25"), - tx_hash: hex!("20bfdae2117df689c699d7b0402bf4878740879fad11350afdf53cc8b7b96b5a").into(), - receipt_hash: hex!("1a40aa2cd1b1e174f8ad0ae1e3f7a9918c6da6297238ffbaa9db907a44b96b6b").into(), - bloom: hex!("1ea0e6d21a3ebf7e894421e68e1475dfc39bc6d28728cb0a322ba16f5a9459128e66116753377025dd23beaa295e2a98c7512c89510c21356d946e983d2f36b87446c66ec3482f288358c668c35449ed6cb2bda772e68b0ae0c5a856d5c38e35cb0d3d268ac7dd012a5f5974257a6deba8c974db8f4f7e270a2b9e58e8e9d39549c8b18626a871996a86a61518c03fcd147564556d74169d399a95dd18da7ca15210288a43e587d5f61e5fcf9ba51556cfb6c5c10d72d2a534364f212f5123e57827950bd790bc4e70d8baeb49303265b967176a950839762f1ad4d2c90de6fdd55ca249bb37d93fc9959eca99030fa03137df6502ab54d5d9323bd2dea1c6df").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8eb6", 16).unwrap(), - gas_limit: u64::from_str_radix("8583b00", 16).unwrap(), - gas_used: u64::from_str_radix("f96c44", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0a6", 16).unwrap(), - extra_data: hex!("d883010209846765746888676f312e32302e36856c696e7578000000b19df4a2f8b5830aefffb860a0138da8d8d9e4f6f61bab7567e04099cf03ada629e8190af22cd4ef64a03f6c429065f576709c7b72cefe9645f4dd9f0ddbfa22e3510b0d4e9a97441d2d00ca1807a072d34cc6551a97c48db9b188de7911f5ec56a061015641787e47fa0917f84c8401dd8eb4a055ac85646e4961091af47efe4cb44edc27446ee7b843e9ca88bd2410cabbd0bc8401dd8eb5a0194822ef17f86aa711f97387a2fed416227806f12a957715630f25a0a060428180f032d9041437495d44595befbb88540d3e87e4a6407fabc164295aa399d967090d860b2500045f33a37a7292d8d9314a0703a075d8e6de54656d16c5d3a64afc01").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("4edb537f71dc11604b10251c74ec65f9f5d8b7b49823a4e6b3fa635043ab066a"), - } -} - -pub fn header_31297205() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8eb5&boolean=false - //https://bscscan.com/block/31297205 - ETHHeader { - parent_hash: hex!("55ac85646e4961091af47efe4cb44edc27446ee7b843e9ca88bd2410cabbd0bc").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("2d4c407bbe49438ed859fe965b140dcf1aab71a9").into(), - root: hex!("0fcf463d8fb2dbff492b65e6f79af26d23e80c288aa7724019aa4cda75652061"), - tx_hash: hex!("1820a50d43fdc3cd2117af385955c896959555b3573590af364c6f8185646a74").into(), - receipt_hash: hex!("f498551fbc5c1298f3ed791a80b76750c6679c21b289a0c56bf3bb0c82491e37").into(), - bloom: hex!("20600602072a1118041000448416040501408082118b09015098050311c641088e00f900202410400100364f171642a483260e38042000082126480200243226240094c8994016a08d30b4c9c280a4a02810b420004e8813a42c0850810000e1cbab30273a261029886d080303492d184814124096c93c141021ac188852063d888a81250648e0919080371602795b08042644056b04009821c03944a0315ce01252611032b2010a2502dc9e0e800000a01001090700118130b60123e45020c8c858048a2642804e00a0886162229808e08801e285402855091ac4420021f5be0c18909084a6812a0190044ab003c982880494bf2031f0d839402481492101da").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8eb5", 16).unwrap(), - gas_limit: u64::from_str_radix("8583b00", 16).unwrap(), - gas_used: u64::from_str_radix("5f1ae3", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0a3", 16).unwrap(), - extra_data: hex!("d88301020a846765746888676f312e31392e38856c696e7578000000b19df4a2f8b5830aefffb860a8b4e7e5f158135b806ad8d725138c902ebce597c98f0205d3b2072b3ac06f1712103a9ba0e6b0da115364a28048d2ee0380cd09eecc422408390e716ef372c1cb6a4795898d0b3136019f53df637ab55aa73afd35b0c1da54a9762be654b472f84c8401dd8eb3a013901357854d7c35878d6ff9a24714e0c21f1beb95e0b55667b915d2d74c729e8401dd8eb4a055ac85646e4961091af47efe4cb44edc27446ee7b843e9ca88bd2410cabbd0bc804f894a2e6797eef8cb87e611a4d04c9d9d382a3025d0f21233992143acfdfd451598f85f09da424e6f1051aa4e3ead85b21a769d177c86d264799f13a4883bfc01").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("194822ef17f86aa711f97387a2fed416227806f12a957715630f25a0a0604281"), - } -} - -pub fn header_31297204() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8eb4&boolean=false - //https://bscscan.com/block/31297204 - ETHHeader { - parent_hash: hex!("13901357854d7c35878d6ff9a24714e0c21f1beb95e0b55667b915d2d74c729e").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("295e26495cef6f69dfa69911d9d8e4f3bbadb89b").into(), - root: hex!("74f96bbe3fdcb97aa80f9865f150a32bd3640761feb026457b8ccf9c81a4d0b3"), - tx_hash: hex!("704032ce0e736aa129323696270ba0c4f4c226770d5a5769b477f20028c69528").into(), - receipt_hash: hex!("85796e78bcf8868383deb17f5794af1ab2a02920410faeb25dcdce0a2114d49f").into(), - bloom: hex!("9feff27efd2db7ffcf7b7a47cdacbe47305ddb6377342ccf63fae53f2861af5e9ea43fd9ecc15ddf1bbefee2cf7e5b0daee7599ef32f7fd3749eeddf6f7cbe9bacdecd9bf95d893fa17ee69f9aa794eaea9287fd53f6aba29fef91678af61e79cf7cbee3ffae8e87956fdf6bffdbadfd9c8ab27dadfb5dcf7267cdfd8fdb8febddefa87757ddbce536cfef151c57efdb97fe7cb77bf3fcdff9fe91dfbcffdcff9f033ad3737b378eb607af6c1fef94d4fc2aea7e9b7acd9df3e963e47ffb55f8eb3b35e31c7cadff7dfa0e6e71fa9bb1e5d7f6eecd29fa35ff57fddef394f9e9bdf3ed7b15e577cb7fbd16ff217a23a6fe76863bf3f35b692b0256b4b9634c5e").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8eb4", 16).unwrap(), - gas_limit: u64::from_str_radix("85832a7", 16).unwrap(), - gas_used: u64::from_str_radix("1ab0be2", 16).unwrap(), - timestamp: u64::from_str_radix("64eee0a0", 16).unwrap(), - extra_data: hex!("d883010209846765746888676f312e32302e36856c696e7578000000b19df4a2f8b5830aefffb860a37f1a0dc4fbaffca02601db7fa52727bfc120101001a10a628b33340ae2437e34bab00c59ee3b77041899328ff816e0011b7f664c9837756fa64c824802ddcc15405628f667d07c6120161e68ef8c6ab2a5b03faf109f53254d9f65747781e4f84c8401dd8eb2a094fd52d22bffdadbdb22f6d8f5ff8843d7bb47cc4ed34170168862437d830c798401dd8eb3a013901357854d7c35878d6ff9a24714e0c21f1beb95e0b55667b915d2d74c729e8096c7d1f1f9dd8df490346a9b3e2f9cc92ee320217cc08dd253159cd50e3029052d9de5c19162eec1be3458eb7cb31e97dc9b656d80e92c681558beec028045da00").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("55ac85646e4961091af47efe4cb44edc27446ee7b843e9ca88bd2410cabbd0bc"), - } -} - -pub fn header_31297203() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8eb3&boolean=false - //https://bscscan.com/block/31297203 - ETHHeader { - parent_hash: hex!("94fd52d22bffdadbdb22f6d8f5ff8843d7bb47cc4ed34170168862437d830c79").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("0bac492386862ad3df4b666bc096b0505bb694da").into(), - root: hex!("a5c326c2677e2d80a74326c1fe409c492f062679664307411e769aee4439b68c"), - tx_hash: hex!("7c506aa939b812971d33f7382e444605b41e4d3c457bca15de3d18a9f9402a69").into(), - receipt_hash: hex!("9db976f1d7b56eec4ef92e0e8e38eafc9141f0359931b7265f59088a37adca9d").into(), - bloom: hex!("4e6ccf91b23a34dacee649efb31f6c7fc6397cc97b6db5d4527ac96c345d4390af6b74c9fbde9f372fee7d6040be274efd351c57268efb67fba605bb9d6b4b9ce6e9edda9b56288381755d3dcaa164bcadbc5334fff2a9bf89bfd521e3e09c4d82bfa1ba7b2f7bd5221da9f1f361ff79db4505473aae0fd6d37ddc51b1672d84339ee90445e57bfb3f96e43798fa2fefbc2d2fe779d29cd92fe40ad3e6da47e5bb0f6afbf7ffe7beeec66fce26efd6dad63f41b953bfd9e5f6b4ef68f4df74697093d70eba27bb7b33da8eefcd9f7e2bf6d783af65dbcf173976de52e20dfd3717faee6fae56fd9f2d9737d69bd3bb66e1732f8af6f446fd7a26d81c6b69efdf").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8eb3", 16).unwrap(), - gas_limit: u64::from_str_radix("84fe2c6", 16).unwrap(), - gas_used: u64::from_str_radix("ee1aa1", 16).unwrap(), - timestamp: u64::from_str_radix("64eee09d", 16).unwrap(), - extra_data: hex!("d88301020a846765746888676f312e32302e35856c696e7578000000b19df4a2f8b5830aefffb860a70735caccfcae04b5262d8f2fddfdde93b01c2b9c05319abb844c5512c30ef105491ebae1898c217ee585b5895159e40068f1f80f52a8d302cad34503cbe3a9d765708388e75c15b3adf8a27697b5afdeaa93d60c4e2668dd15244eb39115d4f84c8401dd8eb1a08398b4664eb55beadbbbb8ec08dbacd78322cb3274dcd8bb53999be2b784cd928401dd8eb2a094fd52d22bffdadbdb22f6d8f5ff8843d7bb47cc4ed34170168862437d830c79809b4e20566a9f785f109a5821474cdabf036fd19e217405b8de50e2deb9896dac59c62c8e39c32e3b48e5e37d335c528bc72ca86f0142959b37cb6a9fe97d76e601").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("13901357854d7c35878d6ff9a24714e0c21f1beb95e0b55667b915d2d74c729e"), - } -} - -pub fn header_31297202() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8eb2&boolean=false - //https://bscscan.com/block/31297202 - ETHHeader { - parent_hash: hex!("8398b4664eb55beadbbbb8ec08dbacd78322cb3274dcd8bb53999be2b784cd92").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("ef0274e31810c9df02f98fafde0f841f4e66a1cd").into(), - root: hex!("66cfd0f3112f0c1b7357852188e303cdca529e96c8f3e27d1e4eb5ac9121255c"), - tx_hash: hex!("9499b3f7096de457472373929f84036a11957a6828e5ba2c10c6965ea10928eb").into(), - receipt_hash: hex!("7604f3125509cfe0fbc0daac26ea9157249e41aabcf2d29297e6ec599e9d8468").into(), - bloom: hex!("04382bc3061d75194854024490983c43e420c0e000a06e022072c5da3e40d51bc64ff507500204244ba0ee82555e020090200028464822a0424c840a5d2320a4c744449b19c030281510944c800400b8333e300110e2669088846b15b0810699884e3e326a0625252c49034b15d26d3b6a66915a8ee965560c29ee93c1e92610108aa0040330e44336eb241f0141cacb1ca53641eb4030b8b81004f10143c926020c144b7aa4ea10064606160ba02cc2f2304094418801333220102ce054e440e010960e94900e4f118801030b851028b601b362e860191e011c546f0000e454143d83192220f31943051e03000689a220812c267738c448a91da51478fd9085").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8eb2", 16).unwrap(), - gas_limit: u64::from_str_radix("8583b00", 16).unwrap(), - gas_used: u64::from_str_radix("11e66dd", 16).unwrap(), - timestamp: u64::from_str_radix("64eee09a", 16).unwrap(), - extra_data: hex!("d88301020a846765746888676f312e32302e34856c696e7578000000b19df4a2f8b5830aefffb86080da9d405971b4aa87a0cc7455c8c86f66aa6be5d85343cd2d10f15aa395b600129bf59b70041f9f985e164dcce52981001cb018d076e501ea825b8a556a90ec79ad203a8adf98ef68f7cb0ef2841a171609db72931976e3077a2f393f86c906f84c8401dd8eb0a0e3439a5ce7e27a9755611e2aed8533ae2b0108ced5610f88d69fc97fd54e832d8401dd8eb1a08398b4664eb55beadbbbb8ec08dbacd78322cb3274dcd8bb53999be2b784cd9280dbd51e8fb1a5fe0e9dd4e5d685af720ee87e267ec8b47d124abb47bbe140eb507aa1ebfd4d57d888c018552c11b7cc7d420b085412fd36b4876f9dd520ea25e700").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("94fd52d22bffdadbdb22f6d8f5ff8843d7bb47cc4ed34170168862437d830c79"), - } -} - -pub fn header_31297201() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8eb1&boolean=false - //https://bscscan.com/block/31297201 - ETHHeader { - parent_hash: hex!("e3439a5ce7e27a9755611e2aed8533ae2b0108ced5610f88d69fc97fd54e832d").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("ea0a6e3c511bbd10f4519ece37dc24887e11b55d").into(), - root: hex!("66aa43298bddd4a09efccab7e2add00410b9af5792f0e1f803a6a2c804013a50"), - tx_hash: hex!("44f85c29cd8b6d584f06fcf870232b226a1d01165202721a1ba9226e06120f1d").into(), - receipt_hash: hex!("fc7d7246d63bf2db119fa1040bcafb763f2445373b6e60e911eb6e3712ebdf4a").into(), - bloom: hex!("c1a4d269e40cd118090c10448f04041680264225c4a58719313045e8122c3993f98116645810782282202ab2411a0834ce50d00851264a204cda822a162422d404ea68558542f4f8877b8889882410bca01a802003c60a0024c48010926418f053bf20a47a2301010157082103311a0a89013153b0a9741c09c01db1804744c4786884a6277d980e00941c184831c99c0027968ded02454c1d0949e8ab824622834300c673e92242240ab7de2aaf5a40cea80109000605c01187a162680a08fda8251c8b4108080e12032961120091243162b16a018445348133557ab021e5643274aa42165e5baa0d930862c98a81e46ab6663322206b6ae332344099035a4a").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8eb1", 16).unwrap(), - gas_limit: u64::from_str_radix("8583b00", 16).unwrap(), - gas_used: u64::from_str_radix("b0b390", 16).unwrap(), - timestamp: u64::from_str_radix("64eee097", 16).unwrap(), - extra_data: hex!("d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a2f8b5830aefffb8608abd3ea492829d7d47af7946a4d68eee74cf3adaa84d322d9df093b34cc5417d1210297861662a3bbe81556aa4e578b80689f641aac1fd578713ae41edc3797678eb051ebd36a7fb5922e4ce2373473bd04488277198b6c9f7129f8d1da8f74bf84c8401dd8eafa010c8358490a494a40c5c92aff8628fa770860a9d34e7fb7df38dfb208b0ddfc38401dd8eb0a0e3439a5ce7e27a9755611e2aed8533ae2b0108ced5610f88d69fc97fd54e832d80d4a280353736fd099c9f594fdf2c71ed5bab28e84720d6034dbe84fb7adeaefd1035b619ed48be9a1fb3ae24306fef5033be712a31e135e51454380685431be600").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("8398b4664eb55beadbbbb8ec08dbacd78322cb3274dcd8bb53999be2b784cd92"), - } -} - -pub fn header_31297200() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=0x1dd8eb0 - //https://bscscan.com/block/31297200 - ETHHeader { - parent_hash: hex!("10c8358490a494a40c5c92aff8628fa770860a9d34e7fb7df38dfb208b0ddfc3").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("e9ae3261a475a27bb1028f140bc2a7c843318afd").into(), - root: hex!("111504390f79560bc7fa5d1d5b8cdb109d0ee1aa76816dba43b88f1e5e152b6f"), - tx_hash: hex!("2a2eb4b95af5c879078702bfccd6147bd47162385898d8c0b81fb94ac5456a60").into(), - receipt_hash: hex!("57ed46152fe61b432e682da7f0b82273e1fee09674b2b62c64952e214e84e7e1").into(), - bloom: hex!("8035164600431418e05400edd0a9650e8238c2833980eadd35538b33d3641594dc00b06042041004a398b01d821aa232cdb11211a044e339d0440056482c6ec80e61d00aa544881a8b61c2988220042db254432900c6c8410045114b80ba0021cd6c20a23a66042b04e7971817460d6c0e52e95a00cbd4809580a4d9804e35c6998a0246256d4ad18588363010a0d89030240cc77a03158a0f4d83c0ac841cb0871050c8f73f6650e6153206369a061a0c2d90835480d12374a021a1605a2278e3209746a6555c4a32a1b8b87a629968238cf242a088ac190b51fa72f200e56c579880051b2042824b1db2e7058003c1619cfc307864e1c8fc2a690299a1864a").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8eb0", 16).unwrap(), - gas_limit: u64::from_str_radix("8583b00", 16).unwrap(), - gas_used: u64::from_str_radix("a136cd", 16).unwrap(), - timestamp: u64::from_str_radix("64eee094", 16).unwrap(), - extra_data: hex!("d88301020a846765746888676f312e32302e35856c696e7578000000b19df4a2150bac492386862ad3df4b666bc096b0505bb694dab0bec348681af766751cb839576e9c515a09c8bffa30a46296ccc56612490eb480d03bf948e10005bbcc0421f90b3d4e2465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c816295e26495cef6f69dfa69911d9d8e4f3bbadb89b977cf58294f7239d515e15b24cfeb82494056cf691eaf729b165f32c9757c429dba5051155903067e56ebe3698678e9135ebb5849518aff370ca25e19e1072cc1a9fabcaa7f3e2c0b4b16ad183c473bafe30a36e39fa4a143657e229cd23c77f8fbc8e4e4e241695dd3d248d1e51521eee6619143f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a61dd481a114a2e761c554b641742c973867899d38a80967d39e406a0a9642d41e9007a27fc1150a267d143a9f786cd2b5eecbdcc4036273705225b956d5e2f8f5eb95d2569c77a677c40c7fbea129d4b171a39b7a8ddabfab2317f59d86abfaf690850223d90e9e7593d91a29331dfc2f84d5adecc75fc39ecab4632c1b4400a3dd1e1298835bcca70f657164e5b75689b64b7fd1fa275f334f28e1896a26afa1295da81418593bd12814463d9f6e45c36a0e47eb4cd3e5b6af29c41e2a3a5636430155a466e216585af3ba772b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a517ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e8b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d78869485a6f79b60359f141df90a0c745125b131caaffd12b772e180fbf38a051c97dabc8aaa0126a233a9e828cdafcc7422c4bb1f4030a56ba364c54103f26bad91508b5220b741b218c5d6af1f979ac42bc68d98a5a0d796c6ab01b659ad0fbd9f515893fdd740b29ba0772dbde9b4635921dd91bd2963a0fc855e31f6338f45b211c4e9dedb7f2eb09de7b4dd66d7c2c7e57f628210187192fb89d4b99dd4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cdcc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a419d1d6bf74282782b0b3eb1413c901d6ecf02e8e28939e8fb41b682372335be8070199ad3e8621d1743bcac4cc9d8f0f6e10f41e56461385c8eb5daac804fe3f2bca6ce739d93dbfb27e027f5e9e6da52b9e1c413ce35adc11000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c192183ee226379db83cffc681495730c11fdde79ba4c0cae7bc6faa3f0cc3e6093b633fd7ee4f86970926958d0b7ec80437f936acf212b78f0cd095f4565fff144fd458d233a5bef0274e31810c9df02f98fafde0f841f4e66a1cd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f8b5830aefffb86097bc63a64e8d730014c39dcaac8f3309e37a11c06f0f5c233b55ba19c1f6c34d2d08de4b030ce825bb21fd884bc0fcb811336857419f5ca42a92ac149a4661a248de10f4ca6496069fdfd10d43bc74ccb81806b6ecd384617d1006b16dead7e4f84c8401dd8eaea0e61c6075d2ab24fcdc423764c21771cac6b241cbff89718f9cc8fc6459b4e7578401dd8eafa010c8358490a494a40c5c92aff8628fa770860a9d34e7fb7df38dfb208b0ddfc380ff15abfc44495e4d4605458bb485f0cac5a152b380a8d0208b3f9ff6216230ec4dd67a73b72b1d17a888c68e111f806ef0b255d012b5185b7420b5fb529c9b9300").to_vec(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("e3439a5ce7e27a9755611e2aed8533ae2b0108ced5610f88d69fc97fd54e832d"), - } -} - -pub fn header_31297199() -> ETHHeader { - //https://api.bscscan.com/api?module=proxy&action=eth_getBlockByNumber&tag=1dd8eaf - //https://bscscan.com/block/31297199 - ETHHeader { - parent_hash: hex!("e61c6075d2ab24fcdc423764c21771cac6b241cbff89718f9cc8fc6459b4e757").into(), - uncle_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), - coinbase: hex!("e2d3a739effcd3a99387d015e260eefac72ebea1").into(), - root: hex!("79882967d449ce9bc320968cc8b2a4d5141d27235e0a3b8647114c9afe26cdae"), - tx_hash: hex!("bba0dedac6654b0c9b2ead8540faace77e2eec65aa2a1bf7189397c5b37eefc5").into(), - receipt_hash: hex!("74fb2a419cffbaf9ea8aa8711899dddb76639a5eea1102abe4d4caf794d2c409").into(), - bloom: hex!("426ec250a2c014988a8081ec954660c7b941c01083e287a2a0fa61b8403103328c18584060eb9e00d62aa103113e0190e98a813c152e4b0144a30b0400a420c14464240209422c21693c6d89b8a4057c2930a83909c4193e103c01008800af1605ec40260a4e04490018908103425812084429581001dcaa95c6ceb389d9062051492e0cd73d403f0bd52708a41989e85036058d68400159a72094f2d982c4e09e5a94135a182246a3080e0d9a5b4c70402010010326238513a075a1cc12108c680435073016480654510d54a08192296c5131ca020dc87569fb5096bd0cea22b090b20289d8d72af1951443a90107e0480604e804a241cc20423d851b451d56").into(), - difficulty: 2, - number: u64::from_str_radix("1dd8eaf", 16).unwrap(), - gas_limit: u64::from_str_radix("8583b00", 16).unwrap(), - gas_used: u64::from_str_radix("9daecd", 16).unwrap(), - timestamp: u64::from_str_radix("64eee091", 16).unwrap(), - extra_data: hex!("d88301020b846765746888676f312e31392e38856c696e7578000000b19df4a2f8b5830aefffb860a53360350c20ceeff8f5200b10570f4bd76773f1cad27b3943435bc40931ac21db839c0ea70186c139029911221139880bdc23b8e74ddca923693c4d217a27eb7a59d88fedefa954d0566dba8033fc1c6aee879befea2f81006086f2ccb43a8bf84c8401dd8eada0ea1d6d560cc573e0d821a0cfcc527ad381bcfe0f6e93ccbca6ddb014ae8eee118401dd8eaea0e61c6075d2ab24fcdc423764c21771cac6b241cbff89718f9cc8fc6459b4e757808252eeb717f3c64e36b0901a76e1e66d1f7228c01bd59734004746c9d43fa110161087c72ecd1015671cb6d382744ec8613fb944322255482ccf73bbdebad32f01").into(), - mix_digest: hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - nonce: hex!("0000000000000000").into(), - hash: hex!("10c8358490a494a40c5c92aff8628fa770860a9d34e7fb7df38dfb208b0ddfc3"), - } -} diff --git a/light-client/src/header/validator_set.rs b/light-client/src/header/validator_set.rs index 02dacc7..7bc7d1e 100644 --- a/light-client/src/header/validator_set.rs +++ b/light-client/src/header/validator_set.rs @@ -1,85 +1,6 @@ -use crate::errors::Error; use alloc::vec::Vec; -use crate::misc::{ceil_div, keccak_256_vec, Hash, Validators}; - -#[derive(Clone, Debug, PartialEq)] -pub struct TrustedValidatorSet<'a> { - inner: &'a ValidatorSet, -} - -impl<'a> TrustedValidatorSet<'a> { - pub fn validators(&self) -> &Validators { - &self.inner.validators - } - - pub fn checkpoint(&self) -> u64 { - self.inner.checkpoint() - } - - pub fn new(inner: &'a ValidatorSet) -> Self { - Self { inner } - } -} - -#[derive(Clone, Debug, PartialEq)] -pub struct UntrustedValidatorSet<'a> { - inner: &'a ValidatorSet, -} - -impl<'a> UntrustedValidatorSet<'a> { - pub fn new(inner: &'a ValidatorSet) -> Self { - Self { inner } - } - pub fn checkpoint(&self) -> u64 { - self.inner.checkpoint() - } - pub fn try_borrow( - &'a self, - trusted_validators: &TrustedValidatorSet, - ) -> Result<&'a Validators, Error> { - let (result, found, required) = self.contains(trusted_validators); - if result { - return Ok(&self.inner.validators); - } - Err(Error::InsufficientTrustedValidatorsInUntrustedValidators( - self.inner.hash, - found, - required, - )) - } - - fn contains(&self, trusted_validators: &TrustedValidatorSet) -> (bool, usize, usize) { - let trusted_validators = trusted_validators.validators(); - let mut trusted_validator_count = 0; - for x1 in &self.inner.validators { - if trusted_validators.contains(x1) { - trusted_validator_count += 1; - } - } - let required = ceil_div(trusted_validators.len(), 3); - ( - trusted_validator_count >= required, - trusted_validator_count, - required, - ) - } -} - -#[derive(Clone, Debug, PartialEq)] -pub enum EitherValidatorSet<'a> { - Trusted(TrustedValidatorSet<'a>), - Untrusted(UntrustedValidatorSet<'a>), -} - -impl<'a> EitherValidatorSet<'a> { - pub fn checkpoint(&self) -> u64 { - match self { - EitherValidatorSet::Trusted(v) => v.checkpoint(), - EitherValidatorSet::Untrusted(v) => v.checkpoint(), - } - } -} +use crate::misc::{keccak_256_vec, Hash, Validators}; #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] pub struct ValidatorSet { @@ -88,12 +9,12 @@ pub struct ValidatorSet { } impl ValidatorSet { - /// for example when the validator count is 21 the checkpoint is 211, 411, 611 ... - /// https://github.com/bnb-chain/bsc/blob/48aaee69e9cb50fc2cedf1398ae4b98b099697db/consensus/parlia/parlia.go#L607 - /// https://github.com/bnb-chain/bsc/blob/48aaee69e9cb50fc2cedf1398ae4b98b099697db/consensus/parlia/snapshot.go#L191 - pub fn checkpoint(&self) -> u64 { + pub fn checkpoint(&self, turn_length: u8) -> u64 { let validator_size = self.validators.len() as u64; - validator_size / 2 + 1 + (validator_size / 2 + 1) * turn_length as u64 + // https://github.com/bnb-chain/BEPs/pull/341 + // The validator set switch occurs only when the block height reaches Bswitch to prevent epoch block forging. + // Bswitch%epochSlots + 1 = checkpoint } } @@ -106,181 +27,3 @@ impl From>> for ValidatorSet { } } } - -#[cfg(test)] -mod test { - use crate::errors::Error; - use crate::header::validator_set::{TrustedValidatorSet, UntrustedValidatorSet, ValidatorSet}; - - #[test] - pub fn test_untrusted_validator_set_try_borrow() { - let mut _assert_trusted = |x, y, c_val_borrowable| { - let trusted_validators: ValidatorSet = vec![ - vec![1], - vec![2], - vec![3], - vec![4], - vec![5], - vec![6], - vec![7], - ] - .into(); - let trusted_validators = TrustedValidatorSet::new(&trusted_validators); - let untrusted_validators = ValidatorSet { - validators: x, - hash: [0; 32], - }; - let untrusted_validators = UntrustedValidatorSet::new(&untrusted_validators); - let (result, count, required) = untrusted_validators.contains(&trusted_validators); - assert_eq!(result, c_val_borrowable); - assert_eq!(count, y); - assert_eq!(required, 3); - match untrusted_validators.try_borrow(&trusted_validators) { - Ok(borrowed) => { - if c_val_borrowable { - assert_eq!(*borrowed, untrusted_validators.inner.validators); - } else { - unreachable!("unexpected borrowed") - } - } - Err(e) => { - if c_val_borrowable { - unreachable!("unexpected error {:?}", e); - } else { - match e { - Error::InsufficientTrustedValidatorsInUntrustedValidators(_, _, _) => {} - e => unreachable!("unexpected error type {:?}", e), - } - } - } - } - }; - - let assert_trusted = |x, y| _assert_trusted(x, y, true); - assert_trusted( - vec![ - vec![1], - vec![2], - vec![3], - vec![4], - vec![5], - vec![6], - vec![7], - ], - 7, - ); - assert_trusted( - vec![ - vec![1], - vec![2], - vec![3], - vec![4], - vec![15], - vec![16], - vec![17], - ], - 4, - ); - assert_trusted( - vec![ - vec![11], - vec![12], - vec![13], - vec![4], - vec![5], - vec![6], - vec![7], - ], - 4, - ); - assert_trusted( - vec![ - vec![1], - vec![12], - vec![3], - vec![14], - vec![5], - vec![16], - vec![7], - ], - 4, - ); - assert_trusted(vec![vec![1], vec![2], vec![3], vec![4]], 4); - assert_trusted( - vec![ - vec![1], - vec![2], - vec![3], - vec![14], - vec![15], - vec![16], - vec![17], - ], - 3, - ); - assert_trusted( - vec![ - vec![11], - vec![12], - vec![13], - vec![14], - vec![5], - vec![6], - vec![7], - ], - 3, - ); - assert_trusted( - vec![ - vec![1], - vec![12], - vec![3], - vec![14], - vec![5], - vec![16], - vec![17], - ], - 3, - ); - assert_trusted(vec![vec![1], vec![2], vec![3]], 3); - - let assert_untrusted = |x, y| _assert_trusted(x, y, false); - assert_untrusted( - vec![ - vec![1], - vec![2], - vec![13], - vec![14], - vec![15], - vec![16], - vec![17], - ], - 2, - ); - assert_untrusted( - vec![ - vec![11], - vec![12], - vec![13], - vec![14], - vec![15], - vec![6], - vec![7], - ], - 2, - ); - assert_untrusted( - vec![ - vec![1], - vec![12], - vec![3], - vec![14], - vec![15], - vec![16], - vec![17], - ], - 2, - ); - assert_untrusted(vec![vec![1], vec![2]], 2); - } -} diff --git a/light-client/src/header/vote_attestation.rs b/light-client/src/header/vote_attestation.rs index f25630d..f3f4f56 100644 --- a/light-client/src/header/vote_attestation.rs +++ b/light-client/src/header/vote_attestation.rs @@ -147,15 +147,16 @@ impl<'a> TryFrom> for VoteAttestation { #[cfg(test)] mod test { use crate::errors::Error; - use crate::header::testdata::{ - header_31297199, header_31297200, header_31297201, header_31297202, validators_in_31297000, - }; + use crate::fixture::*; use crate::header::vote_attestation::{ VoteAddressBitSet, VoteAttestation, VoteData, BLS_SIGNATURE_LENGTH, MAX_ATTESTATION_EXTRA_LENGTH, }; + use crate::misc::ceil_div; use hex_literal::hex; use rlp::{Rlp, RlpStream}; + use rstest::rstest; + use std::prelude::rust_2015::Box; #[test] fn test_error_try_from_unexpected_bls_signature_length() { @@ -195,23 +196,19 @@ mod test { }; } - #[test] - fn test_success_verify() { - let validators = validators_in_31297000(); - let blocks = vec![ - header_31297199(), - header_31297200(), - header_31297201(), - header_31297202(), - ]; + #[rstest] + #[case::localnet(localnet())] + fn test_success_verify(#[case] hp: Box) { + let validators = hp + .previous_epoch_header() + .epoch + .unwrap() + .validators() + .clone(); + let blocks = hp.headers_before_checkpoint().all; for block in blocks.iter() { - if let Err(e) = block - .get_vote_attestation() - .unwrap() - .verify(block.number, &validators) - { - unreachable!("{} {:?}", block.number, e); - } + let vote = block.get_vote_attestation().unwrap(); + vote.verify(block.number, &validators).unwrap(); } } @@ -285,68 +282,67 @@ mod test { ); } - #[test] - fn test_error_verify() { - let mut validators = validators_in_31297000(); - validators.extend(validators.clone()); - let header = header_31297199(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_verify(#[case] hp: Box) { + let mut validators = hp.previous_validators(); + validators.extend(validators.clone()); // len = validators * 2 + let header = hp.epoch_header(); let vote = header.get_vote_attestation().unwrap(); let err = vote.verify(header.number, &validators).unwrap_err(); match err { Error::InsufficientValidatorCount(number, vote_count_in_extra, required) => { assert_eq!(number, header.number); - assert_eq!(vote_count_in_extra, 17); - assert_eq!(required, 28); //42 * 2 / 3 + assert_eq!(required, ceil_div(validators.len() * 2, 3)); + assert!(vote_count_in_extra < required); } _ => unreachable!("invalid error {:?}", err), } - let validators = validators_in_31297000()[0..16].to_vec(); + let validators = hp.previous_validators()[0..1].to_vec(); let err = vote.verify(header.number, &validators).unwrap_err(); match err { Error::UnexpectedVoteAddressCount(number, vote_count_in_extra, val_size) => { assert_eq!(number, header.number); - assert_eq!(vote_count_in_extra, 17); assert_eq!(val_size, validators.len()); + assert!(vote_count_in_extra > validators.len()); } _ => unreachable!("{} {:?}", header.number, err), } - let mut validators = validators_in_31297000(); + let mut validators = hp.previous_validators(); for v in validators.iter_mut() { v.pop(); } let err = vote.verify(header.number, &validators).unwrap_err(); match err { - Error::UnexpectedBLSPubkey(number, e) => { + Error::UnexpectedBLSPubkey(number, _) => { assert_eq!(header.number, number); - assert_eq!(format!("{:?}", e), "InvalidPoint"); } _ => unreachable!("{} {:?}", header.number, err), } - let validators = validators_in_31297000(); - let header = header_31297199(); + let validators = hp.previous_validators(); + let header = hp.epoch_header(); let mut vote = header.get_vote_attestation().unwrap(); vote.app_signature[0] = 1; let err = vote.verify(header.number, &validators).unwrap_err(); match err { - Error::UnexpectedBLSSignature(number, e) => { + Error::UnexpectedBLSSignature(number, _e) => { assert_eq!(number, header.number); - assert_eq!(format!("{:?}", e), "InvalidG2Size"); } _ => unreachable!("{} {:?}", header.number, err), } - let validators = validators_in_31297000(); - let header = header_31297199(); + let validators = hp.previous_validators(); + let header = hp.epoch_header(); let mut vote = header.get_vote_attestation().unwrap(); vote.vote_address_set.vote_address_set.pop(); let err = vote.verify(header.number, &validators).unwrap_err(); match err { Error::FailedToVerifyBLSSignature(number, e) => { assert_eq!(number, header.number); - assert_eq!(e, 16); + assert_eq!(e, validators.len() - 1); } _ => unreachable!("{} {:?}", header.number, err), } diff --git a/light-client/src/lib.rs b/light-client/src/lib.rs index 4c1676d..5492d5d 100644 --- a/light-client/src/lib.rs +++ b/light-client/src/lib.rs @@ -11,6 +11,8 @@ pub mod client_state; pub mod commitment; pub mod consensus_state; pub mod errors; +#[cfg(test)] +mod fixture; pub mod header; pub mod message; pub mod misbehaviour; diff --git a/light-client/src/misbehaviour.rs b/light-client/src/misbehaviour.rs index 18c3fb3..fb2e63c 100644 --- a/light-client/src/misbehaviour.rs +++ b/light-client/src/misbehaviour.rs @@ -69,23 +69,27 @@ mod test { use crate::errors::Error; use crate::header::eth_header::ETHHeader; - use crate::header::testdata::{header_31297201, header_31297202}; + use crate::fixture::*; use crate::misbehaviour::Misbehaviour; use crate::misc::new_height; use alloc::string::ToString; + use rstest::rstest; + use std::prelude::rust_2015::Box; use parlia_ibc_proto::ibc::core::client::v1::Height; - use parlia_ibc_proto::ibc::lightclients::parlia::v1::Header as RawHeader; use parlia_ibc_proto::ibc::lightclients::parlia::v1::Misbehaviour as RawMisbehaviour; + use parlia_ibc_proto::ibc::lightclients::parlia::v1::{EthHeader, Header as RawHeader}; - fn to_raw(h: ÐHeader) -> RawHeader { + fn to_raw(h: alloc::vec::Vec, coinbase: alloc::vec::Vec) -> RawHeader { RawHeader { - headers: vec![h.try_into().unwrap()], + headers: vec![EthHeader { header: h }], trusted_height: Some(Height::default()), account_proof: vec![], - current_validators: vec![h.coinbase.clone()], - previous_validators: vec![h.coinbase.clone()], + current_validators: vec![coinbase.clone()], + previous_validators: vec![coinbase], + previous_turn_length: 1, + current_turn_length: 1, } } @@ -115,12 +119,13 @@ mod test { } } - #[test] - fn test_error_try_from_missing_h2() { - let h1 = header_31297201(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_try_from_missing_h2(#[case] hp: Box) { + let h1 = hp.epoch_header_plus_1(); let src = RawMisbehaviour { client_id: "xx-parlia-1".to_string(), - header_1: Some(to_raw(&h1)), + header_1: Some(to_raw(hp.epoch_header_plus_1_rlp(), h1.coinbase)), header_2: None, }; match Misbehaviour::try_from(src).unwrap_err() { @@ -129,13 +134,14 @@ mod test { } } - #[test] - fn test_error_try_from_same_block() { - let h1 = header_31297201(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_try_from_same_block(#[case] hp: Box) { + let h1 = hp.epoch_header(); let src = RawMisbehaviour { client_id: "xx-parlia-1".to_string(), - header_1: Some(to_raw(&h1)), - header_2: Some(to_raw(&h1)), + header_1: Some(to_raw(hp.epoch_header_rlp(), h1.coinbase.clone())), + header_2: Some(to_raw(hp.epoch_header_rlp(), h1.coinbase)), }; match Misbehaviour::try_from(src).unwrap_err() { Error::UnexpectedSameBlockHash(height) => assert_eq!(height, new_height(0, h1.number)), @@ -143,14 +149,15 @@ mod test { } } - #[test] - fn test_error_try_from_different_height() { - let h1 = header_31297201(); - let h2 = header_31297202(); + #[rstest] + #[case::localnet(localnet())] + fn test_error_try_from_different_height(#[case] hp: Box) { + let h1 = hp.epoch_header(); + let h2 = hp.epoch_header_plus_1(); let src = RawMisbehaviour { client_id: "xx-parlia-1".to_string(), - header_1: Some(to_raw(&h1)), - header_2: Some(to_raw(&h2)), + header_1: Some(to_raw(hp.epoch_header_rlp(), h1.coinbase)), + header_2: Some(to_raw(hp.epoch_header_plus_1_rlp(), h2.coinbase)), }; match Misbehaviour::try_from(src).unwrap_err() { Error::UnexpectedDifferentHeight(h1_height, h2_height) => { @@ -161,19 +168,22 @@ mod test { } } - #[test] - fn test_success_try_from() { - let h1 = header_31297201(); - let mut h2 = header_31297201(); - h2.gas_used = h1.gas_used + 1; + #[rstest] + #[case::localnet(localnet())] + fn test_success_try_from(#[case] hp: Box) { + let h1 = hp.epoch_header_plus_1(); + let mut h2 = hp.epoch_header_plus_1_rlp(); + let size = h2.len(); + h2[size - 1] = 1; // set excess blob gas + let _v = ETHHeader::try_from(EthHeader { header: h2.clone() }); let src = RawMisbehaviour { client_id: "xx-parlia-1".to_string(), - header_1: Some(to_raw(&h1)), - header_2: Some(to_raw(&h2)), + header_1: Some(to_raw(hp.epoch_header_plus_1_rlp(), h1.coinbase.clone())), + header_2: Some(to_raw(h2, h1.coinbase)), }; let misbehaviour = Misbehaviour::try_from(src).unwrap(); assert_eq!(misbehaviour.client_id.as_str(), "xx-parlia-1"); assert_eq!(misbehaviour.header_1.height(), new_height(0, h1.number)); - assert_eq!(misbehaviour.header_2.height(), new_height(0, h2.number)); + assert_eq!(misbehaviour.header_2.height(), new_height(0, h1.number)); } } diff --git a/proto/definitions/ibc/lightclients/parlia/v1/parlia.proto b/proto/definitions/ibc/lightclients/parlia/v1/parlia.proto index c7131ae..5c70350 100644 --- a/proto/definitions/ibc/lightclients/parlia/v1/parlia.proto +++ b/proto/definitions/ibc/lightclients/parlia/v1/parlia.proto @@ -31,6 +31,8 @@ message Header { bytes account_proof = 3; repeated bytes current_validators = 4; repeated bytes previous_validators = 5; + uint32 current_turn_length = 6; + uint32 previous_turn_length = 7; } message ConsensusState { diff --git a/proto/src/prost/cosmos.upgrade.v1beta1.rs b/proto/src/prost/cosmos.upgrade.v1beta1.rs index 634b0aa..c46a9aa 100644 --- a/proto/src/prost/cosmos.upgrade.v1beta1.rs +++ b/proto/src/prost/cosmos.upgrade.v1beta1.rs @@ -12,8 +12,10 @@ pub struct Plan { /// reached and the software will exit. #[prost(string, tag = "1")] pub name: ::prost::alloc::string::String, - /// The time after which the upgrade must be performed. - /// Leave set to its zero value to use a pre-defined Height instead. + /// Deprecated: Time based upgrades have been deprecated. Time based upgrade logic + /// has been removed from the SDK. + /// If this field is not empty, an error will be thrown. + #[deprecated] #[prost(message, optional, tag = "2")] pub time: ::core::option::Option, /// The height at which the upgrade must be performed. @@ -24,6 +26,14 @@ pub struct Plan { /// such as a git commit that validators could automatically upgrade to #[prost(string, tag = "4")] pub info: ::prost::alloc::string::String, + /// Deprecated: UpgradedClientState field has been deprecated. IBC upgrade logic has been + /// moved to the IBC module in the sub module 02-client. + /// If this field is not empty, an error will be thrown. + #[deprecated] + #[prost(message, optional, tag = "5")] + pub upgraded_client_state: ::core::option::Option< + super::super::super::google::protobuf::Any, + >, } /// SoftwareUpgradeProposal is a gov Content type for initiating a software /// upgrade. @@ -49,3 +59,17 @@ pub struct CancelSoftwareUpgradeProposal { #[prost(string, tag = "2")] pub description: ::prost::alloc::string::String, } +/// ModuleVersion specifies a module and its consensus version. +/// +/// Since: cosmos-sdk 0.43 +#[derive(::serde::Serialize, ::serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ModuleVersion { + /// name of the app module + #[prost(string, tag = "1")] + pub name: ::prost::alloc::string::String, + /// consensus version of the app module + #[prost(uint64, tag = "2")] + pub version: u64, +} diff --git a/proto/src/prost/google.protobuf.rs b/proto/src/prost/google.protobuf.rs index 518a909..0c10fc1 100644 --- a/proto/src/prost/google.protobuf.rs +++ b/proto/src/prost/google.protobuf.rs @@ -44,9 +44,14 @@ pub struct FileDescriptorProto { #[prost(message, optional, tag = "9")] pub source_code_info: ::core::option::Option, /// The syntax of the proto file. - /// The supported values are "proto2" and "proto3". + /// The supported values are "proto2", "proto3", and "editions". + /// + /// If `edition` is present, this value must be "editions". #[prost(string, optional, tag = "12")] pub syntax: ::core::option::Option<::prost::alloc::string::String>, + /// The edition of the proto file. + #[prost(enumeration = "Edition", optional, tag = "14")] + pub edition: ::core::option::Option, } /// Describes a message type. #[allow(clippy::derive_partial_eq_without_eq)] @@ -109,6 +114,90 @@ pub struct ExtensionRangeOptions { /// The parser stores options it doesn't recognize here. See above. #[prost(message, repeated, tag = "999")] pub uninterpreted_option: ::prost::alloc::vec::Vec, + /// For external users: DO NOT USE. We are in the process of open sourcing + /// extension declaration and executing internal cleanups before it can be + /// used externally. + #[prost(message, repeated, tag = "2")] + pub declaration: ::prost::alloc::vec::Vec, + /// Any features defined in the specific edition. + #[prost(message, optional, tag = "50")] + pub features: ::core::option::Option, + /// The verification state of the range. + /// TODO: flip the default to DECLARATION once all empty ranges + /// are marked as UNVERIFIED. + #[prost( + enumeration = "extension_range_options::VerificationState", + optional, + tag = "3", + default = "Unverified" + )] + pub verification: ::core::option::Option, +} +/// Nested message and enum types in `ExtensionRangeOptions`. +pub mod extension_range_options { + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct Declaration { + /// The extension number declared within the extension range. + #[prost(int32, optional, tag = "1")] + pub number: ::core::option::Option, + /// The fully-qualified name of the extension field. There must be a leading + /// dot in front of the full name. + #[prost(string, optional, tag = "2")] + pub full_name: ::core::option::Option<::prost::alloc::string::String>, + /// The fully-qualified type name of the extension field. Unlike + /// Metadata.type, Declaration.type must have a leading dot for messages + /// and enums. + #[prost(string, optional, tag = "3")] + pub r#type: ::core::option::Option<::prost::alloc::string::String>, + /// If true, indicates that the number is reserved in the extension range, + /// and any extension field with the number will fail to compile. Set this + /// when a declared extension field is deleted. + #[prost(bool, optional, tag = "5")] + pub reserved: ::core::option::Option, + /// If true, indicates that the extension must be defined as repeated. + /// Otherwise the extension must be defined as optional. + #[prost(bool, optional, tag = "6")] + pub repeated: ::core::option::Option, + } + /// The verification state of the extension range. + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum VerificationState { + /// All the extensions of the range must be declared. + Declaration = 0, + Unverified = 1, + } + impl VerificationState { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + VerificationState::Declaration => "DECLARATION", + VerificationState::Unverified => "UNVERIFIED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "DECLARATION" => Some(Self::Declaration), + "UNVERIFIED" => Some(Self::Unverified), + _ => None, + } + } + } } /// Describes a field within a message. #[allow(clippy::derive_partial_eq_without_eq)] @@ -208,9 +297,10 @@ pub mod field_descriptor_proto { Bool = 8, String = 9, /// Tag-delimited aggregate. - /// Group type is deprecated and not supported in proto3. However, Proto3 + /// Group type is deprecated and not supported after google.protobuf. However, Proto3 /// implementations should still be able to parse the group wire format and - /// treat group fields as unknown fields. + /// treat group fields as unknown fields. In Editions, the group wire format + /// can be enabled via the `message_encoding` feature. Group = 10, /// Length-delimited aggregate. Message = 11, @@ -292,8 +382,11 @@ pub mod field_descriptor_proto { pub enum Label { /// 0 is reserved for errors Optional = 1, - Required = 2, Repeated = 3, + /// The required label is only allowed in google.protobuf. In proto3 and Editions + /// it's explicitly prohibited. In Editions, the `field_presence` feature + /// can be used to get this behavior. + Required = 2, } impl Label { /// String value of the enum field names used in the ProtoBuf definition. @@ -303,16 +396,16 @@ pub mod field_descriptor_proto { pub fn as_str_name(&self) -> &'static str { match self { Label::Optional => "LABEL_OPTIONAL", - Label::Required => "LABEL_REQUIRED", Label::Repeated => "LABEL_REPEATED", + Label::Required => "LABEL_REQUIRED", } } /// Creates an enum from field names used in the ProtoBuf definition. pub fn from_str_name(value: &str) -> ::core::option::Option { match value { "LABEL_OPTIONAL" => Some(Self::Optional), - "LABEL_REQUIRED" => Some(Self::Required), "LABEL_REPEATED" => Some(Self::Repeated), + "LABEL_REQUIRED" => Some(Self::Required), _ => None, } } @@ -521,6 +614,9 @@ pub struct FileOptions { /// determining the ruby package. #[prost(string, optional, tag = "45")] pub ruby_package: ::core::option::Option<::prost::alloc::string::String>, + /// Any features defined in the specific edition. + #[prost(message, optional, tag = "50")] + pub features: ::core::option::Option, /// The parser stores options it doesn't recognize here. /// See the documentation for the "Options" section above. #[prost(message, repeated, tag = "999")] @@ -608,6 +704,10 @@ pub struct MessageOptions { /// this is a formalization for deprecating messages. #[prost(bool, optional, tag = "3", default = "false")] pub deprecated: ::core::option::Option, + /// NOTE: Do not set the option in .proto files. Always use the maps syntax + /// instead. The option should only be implicitly set by the proto compiler + /// parser. + /// /// Whether the message is an automatically generated map entry type for the /// maps field. /// @@ -625,12 +725,24 @@ pub struct MessageOptions { /// use a native map in the target language to hold the keys and values. /// The reflection APIs in such implementations still need to work as /// if the field is a repeated message field. - /// - /// NOTE: Do not set the option in .proto files. Always use the maps syntax - /// instead. The option should only be implicitly set by the proto compiler - /// parser. #[prost(bool, optional, tag = "7")] pub map_entry: ::core::option::Option, + /// Enable the legacy handling of JSON field name conflicts. This lowercases + /// and strips underscored from the fields before comparison in proto3 only. + /// The new behavior takes `json_name` into account and applies to proto2 as + /// well. + /// + /// This should only be used as a temporary measure against broken builds due + /// to the change in behavior for JSON field name conflicts. + /// + /// TODO This is legacy behavior we plan to remove once downstream + /// teams have had time to migrate. + #[deprecated] + #[prost(bool, optional, tag = "11")] + pub deprecated_legacy_json_field_conflicts: ::core::option::Option, + /// Any features defined in the specific edition. + #[prost(message, optional, tag = "12")] + pub features: ::core::option::Option, /// The parser stores options it doesn't recognize here. See above. #[prost(message, repeated, tag = "999")] pub uninterpreted_option: ::prost::alloc::vec::Vec, @@ -640,8 +752,10 @@ pub struct MessageOptions { pub struct FieldOptions { /// The ctype option instructs the C++ code generator to use a different /// representation of the field than it normally would. See the specific - /// options below. This option is not yet implemented in the open source - /// release -- sorry, we'll try to include it in a future version! + /// options below. This option is only implemented to support use of + /// \[ctype=CORD\] and \[ctype=STRING\] (the default) on non-repeated fields of + /// type "bytes" in the open source release -- sorry, we'll try to include + /// other types in a future version! #[prost( enumeration = "field_options::CType", optional, @@ -653,7 +767,9 @@ pub struct FieldOptions { /// a more efficient representation on the wire. Rather than repeatedly /// writing the tag and type for each element, the entire array is encoded as /// a single length-delimited blob. In proto3, only explicit setting it to - /// false will avoid using packed encoding. + /// false will avoid using packed encoding. This option is prohibited in + /// Editions, but the `repeated_field_encoding` feature can be used to control + /// the behavior. #[prost(bool, optional, tag = "2")] pub packed: ::core::option::Option, /// The jstype option determines the JavaScript type used for values of the @@ -691,7 +807,6 @@ pub struct FieldOptions { /// call from multiple threads concurrently, while non-const methods continue /// to require exclusive access. /// - /// /// Note that implementations may choose not to check required fields within /// a lazy sub-message. That is, calling IsInitialized() on the outer message /// may return true even if the inner message has missing required fields. @@ -703,11 +818,8 @@ pub struct FieldOptions { /// check its required fields, regardless of whether or not the message has /// been parsed. /// - /// As of 2021, lazy does no correctness checks on the byte stream during - /// parsing. This may lead to crashes if and when an invalid byte stream is - /// finally parsed upon access. - /// - /// TODO(b/211906113): Enable validation on lazy fields. + /// As of May 2022, lazy verifies the contents of the byte stream during + /// parsing. An invalid byte stream will cause the overall parsing to fail. #[prost(bool, optional, tag = "5", default = "false")] pub lazy: ::core::option::Option, /// unverified_lazy does no correctness checks on the byte stream. This should @@ -724,12 +836,39 @@ pub struct FieldOptions { /// For Google-internal migration only. Do not use. #[prost(bool, optional, tag = "10", default = "false")] pub weak: ::core::option::Option, + /// Indicate that the field value should not be printed out when using debug + /// formats, e.g. when the field contains sensitive credentials. + #[prost(bool, optional, tag = "16", default = "false")] + pub debug_redact: ::core::option::Option, + #[prost(enumeration = "field_options::OptionRetention", optional, tag = "17")] + pub retention: ::core::option::Option, + #[prost( + enumeration = "field_options::OptionTargetType", + repeated, + packed = "false", + tag = "19" + )] + pub targets: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "20")] + pub edition_defaults: ::prost::alloc::vec::Vec, + /// Any features defined in the specific edition. + #[prost(message, optional, tag = "21")] + pub features: ::core::option::Option, /// The parser stores options it doesn't recognize here. See above. #[prost(message, repeated, tag = "999")] pub uninterpreted_option: ::prost::alloc::vec::Vec, } /// Nested message and enum types in `FieldOptions`. pub mod field_options { + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct EditionDefault { + #[prost(enumeration = "super::Edition", optional, tag = "3")] + pub edition: ::core::option::Option, + /// Textproto value. + #[prost(string, optional, tag = "2")] + pub value: ::core::option::Option<::prost::alloc::string::String>, + } #[derive( Clone, Copy, @@ -745,6 +884,12 @@ pub mod field_options { pub enum CType { /// Default mode. String = 0, + /// The option \[ctype=CORD\] may be applied to a non-repeated field of type + /// "bytes". It indicates that in C++, the data should be stored in a Cord + /// instead of a string. For very large strings, this may reduce memory + /// fragmentation. It may also allow better performance when parsing from a + /// Cord, or when parsing with aliasing enabled, as the parsed Cord may then + /// alias the original buffer. Cord = 1, StringPiece = 2, } @@ -812,10 +957,121 @@ pub mod field_options { } } } + /// If set to RETENTION_SOURCE, the option will be omitted from the binary. + /// Note: as of January 2023, support for this is in progress and does not yet + /// have an effect (b/264593489). + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum OptionRetention { + RetentionUnknown = 0, + RetentionRuntime = 1, + RetentionSource = 2, + } + impl OptionRetention { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + OptionRetention::RetentionUnknown => "RETENTION_UNKNOWN", + OptionRetention::RetentionRuntime => "RETENTION_RUNTIME", + OptionRetention::RetentionSource => "RETENTION_SOURCE", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "RETENTION_UNKNOWN" => Some(Self::RetentionUnknown), + "RETENTION_RUNTIME" => Some(Self::RetentionRuntime), + "RETENTION_SOURCE" => Some(Self::RetentionSource), + _ => None, + } + } + } + /// This indicates the types of entities that the field may apply to when used + /// as an option. If it is unset, then the field may be freely used as an + /// option on any kind of entity. Note: as of January 2023, support for this is + /// in progress and does not yet have an effect (b/264593489). + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum OptionTargetType { + TargetTypeUnknown = 0, + TargetTypeFile = 1, + TargetTypeExtensionRange = 2, + TargetTypeMessage = 3, + TargetTypeField = 4, + TargetTypeOneof = 5, + TargetTypeEnum = 6, + TargetTypeEnumEntry = 7, + TargetTypeService = 8, + TargetTypeMethod = 9, + } + impl OptionTargetType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + OptionTargetType::TargetTypeUnknown => "TARGET_TYPE_UNKNOWN", + OptionTargetType::TargetTypeFile => "TARGET_TYPE_FILE", + OptionTargetType::TargetTypeExtensionRange => { + "TARGET_TYPE_EXTENSION_RANGE" + } + OptionTargetType::TargetTypeMessage => "TARGET_TYPE_MESSAGE", + OptionTargetType::TargetTypeField => "TARGET_TYPE_FIELD", + OptionTargetType::TargetTypeOneof => "TARGET_TYPE_ONEOF", + OptionTargetType::TargetTypeEnum => "TARGET_TYPE_ENUM", + OptionTargetType::TargetTypeEnumEntry => "TARGET_TYPE_ENUM_ENTRY", + OptionTargetType::TargetTypeService => "TARGET_TYPE_SERVICE", + OptionTargetType::TargetTypeMethod => "TARGET_TYPE_METHOD", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "TARGET_TYPE_UNKNOWN" => Some(Self::TargetTypeUnknown), + "TARGET_TYPE_FILE" => Some(Self::TargetTypeFile), + "TARGET_TYPE_EXTENSION_RANGE" => Some(Self::TargetTypeExtensionRange), + "TARGET_TYPE_MESSAGE" => Some(Self::TargetTypeMessage), + "TARGET_TYPE_FIELD" => Some(Self::TargetTypeField), + "TARGET_TYPE_ONEOF" => Some(Self::TargetTypeOneof), + "TARGET_TYPE_ENUM" => Some(Self::TargetTypeEnum), + "TARGET_TYPE_ENUM_ENTRY" => Some(Self::TargetTypeEnumEntry), + "TARGET_TYPE_SERVICE" => Some(Self::TargetTypeService), + "TARGET_TYPE_METHOD" => Some(Self::TargetTypeMethod), + _ => None, + } + } + } } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct OneofOptions { + /// Any features defined in the specific edition. + #[prost(message, optional, tag = "1")] + pub features: ::core::option::Option, /// The parser stores options it doesn't recognize here. See above. #[prost(message, repeated, tag = "999")] pub uninterpreted_option: ::prost::alloc::vec::Vec, @@ -833,6 +1089,18 @@ pub struct EnumOptions { /// is a formalization for deprecating enums. #[prost(bool, optional, tag = "3", default = "false")] pub deprecated: ::core::option::Option, + /// Enable the legacy handling of JSON field name conflicts. This lowercases + /// and strips underscored from the fields before comparison in proto3 only. + /// The new behavior takes `json_name` into account and applies to proto2 as + /// well. + /// TODO Remove this legacy behavior once downstream teams have + /// had time to migrate. + #[deprecated] + #[prost(bool, optional, tag = "6")] + pub deprecated_legacy_json_field_conflicts: ::core::option::Option, + /// Any features defined in the specific edition. + #[prost(message, optional, tag = "7")] + pub features: ::core::option::Option, /// The parser stores options it doesn't recognize here. See above. #[prost(message, repeated, tag = "999")] pub uninterpreted_option: ::prost::alloc::vec::Vec, @@ -846,6 +1114,14 @@ pub struct EnumValueOptions { /// this is a formalization for deprecating enum values. #[prost(bool, optional, tag = "1", default = "false")] pub deprecated: ::core::option::Option, + /// Any features defined in the specific edition. + #[prost(message, optional, tag = "2")] + pub features: ::core::option::Option, + /// Indicate that fields annotated with this enum value should not be printed + /// out when using debug formats, e.g. when the field contains sensitive + /// credentials. + #[prost(bool, optional, tag = "3", default = "false")] + pub debug_redact: ::core::option::Option, /// The parser stores options it doesn't recognize here. See above. #[prost(message, repeated, tag = "999")] pub uninterpreted_option: ::prost::alloc::vec::Vec, @@ -853,6 +1129,9 @@ pub struct EnumValueOptions { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ServiceOptions { + /// Any features defined in the specific edition. + #[prost(message, optional, tag = "34")] + pub features: ::core::option::Option, /// Is this service deprecated? /// Depending on the target platform, this can emit Deprecated annotations /// for the service, or it will be completely ignored; in the very least, @@ -879,6 +1158,9 @@ pub struct MethodOptions { default = "IdempotencyUnknown" )] pub idempotency_level: ::core::option::Option, + /// Any features defined in the specific edition. + #[prost(message, optional, tag = "35")] + pub features: ::core::option::Option, /// The parser stores options it doesn't recognize here. See above. #[prost(message, repeated, tag = "999")] pub uninterpreted_option: ::prost::alloc::vec::Vec, @@ -972,6 +1254,303 @@ pub mod uninterpreted_option { pub is_extension: bool, } } +/// TODO Enums in C++ gencode (and potentially other languages) are +/// not well scoped. This means that each of the feature enums below can clash +/// with each other. The short names we've chosen maximize call-site +/// readability, but leave us very open to this scenario. A future feature will +/// be designed and implemented to handle this, hopefully before we ever hit a +/// conflict here. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct FeatureSet { + #[prost(enumeration = "feature_set::FieldPresence", optional, tag = "1")] + pub field_presence: ::core::option::Option, + #[prost(enumeration = "feature_set::EnumType", optional, tag = "2")] + pub enum_type: ::core::option::Option, + #[prost(enumeration = "feature_set::RepeatedFieldEncoding", optional, tag = "3")] + pub repeated_field_encoding: ::core::option::Option, + #[prost(enumeration = "feature_set::Utf8Validation", optional, tag = "4")] + pub utf8_validation: ::core::option::Option, + #[prost(enumeration = "feature_set::MessageEncoding", optional, tag = "5")] + pub message_encoding: ::core::option::Option, + #[prost(enumeration = "feature_set::JsonFormat", optional, tag = "6")] + pub json_format: ::core::option::Option, +} +/// Nested message and enum types in `FeatureSet`. +pub mod feature_set { + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum FieldPresence { + Unknown = 0, + Explicit = 1, + Implicit = 2, + LegacyRequired = 3, + } + impl FieldPresence { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + FieldPresence::Unknown => "FIELD_PRESENCE_UNKNOWN", + FieldPresence::Explicit => "EXPLICIT", + FieldPresence::Implicit => "IMPLICIT", + FieldPresence::LegacyRequired => "LEGACY_REQUIRED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "FIELD_PRESENCE_UNKNOWN" => Some(Self::Unknown), + "EXPLICIT" => Some(Self::Explicit), + "IMPLICIT" => Some(Self::Implicit), + "LEGACY_REQUIRED" => Some(Self::LegacyRequired), + _ => None, + } + } + } + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum EnumType { + Unknown = 0, + Open = 1, + Closed = 2, + } + impl EnumType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + EnumType::Unknown => "ENUM_TYPE_UNKNOWN", + EnumType::Open => "OPEN", + EnumType::Closed => "CLOSED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "ENUM_TYPE_UNKNOWN" => Some(Self::Unknown), + "OPEN" => Some(Self::Open), + "CLOSED" => Some(Self::Closed), + _ => None, + } + } + } + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum RepeatedFieldEncoding { + Unknown = 0, + Packed = 1, + Expanded = 2, + } + impl RepeatedFieldEncoding { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + RepeatedFieldEncoding::Unknown => "REPEATED_FIELD_ENCODING_UNKNOWN", + RepeatedFieldEncoding::Packed => "PACKED", + RepeatedFieldEncoding::Expanded => "EXPANDED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "REPEATED_FIELD_ENCODING_UNKNOWN" => Some(Self::Unknown), + "PACKED" => Some(Self::Packed), + "EXPANDED" => Some(Self::Expanded), + _ => None, + } + } + } + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum Utf8Validation { + Unknown = 0, + None = 1, + Verify = 2, + } + impl Utf8Validation { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Utf8Validation::Unknown => "UTF8_VALIDATION_UNKNOWN", + Utf8Validation::None => "NONE", + Utf8Validation::Verify => "VERIFY", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "UTF8_VALIDATION_UNKNOWN" => Some(Self::Unknown), + "NONE" => Some(Self::None), + "VERIFY" => Some(Self::Verify), + _ => None, + } + } + } + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum MessageEncoding { + Unknown = 0, + LengthPrefixed = 1, + Delimited = 2, + } + impl MessageEncoding { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + MessageEncoding::Unknown => "MESSAGE_ENCODING_UNKNOWN", + MessageEncoding::LengthPrefixed => "LENGTH_PREFIXED", + MessageEncoding::Delimited => "DELIMITED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "MESSAGE_ENCODING_UNKNOWN" => Some(Self::Unknown), + "LENGTH_PREFIXED" => Some(Self::LengthPrefixed), + "DELIMITED" => Some(Self::Delimited), + _ => None, + } + } + } + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum JsonFormat { + Unknown = 0, + Allow = 1, + LegacyBestEffort = 2, + } + impl JsonFormat { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + JsonFormat::Unknown => "JSON_FORMAT_UNKNOWN", + JsonFormat::Allow => "ALLOW", + JsonFormat::LegacyBestEffort => "LEGACY_BEST_EFFORT", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "JSON_FORMAT_UNKNOWN" => Some(Self::Unknown), + "ALLOW" => Some(Self::Allow), + "LEGACY_BEST_EFFORT" => Some(Self::LegacyBestEffort), + _ => None, + } + } + } +} +/// A compiled specification for the defaults of a set of features. These +/// messages are generated from FeatureSet extensions and can be used to seed +/// feature resolution. The resolution with this object becomes a simple search +/// for the closest matching edition, followed by proto merges. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct FeatureSetDefaults { + #[prost(message, repeated, tag = "1")] + pub defaults: ::prost::alloc::vec::Vec< + feature_set_defaults::FeatureSetEditionDefault, + >, + /// The minimum supported edition (inclusive) when this was constructed. + /// Editions before this will not have defaults. + #[prost(enumeration = "Edition", optional, tag = "4")] + pub minimum_edition: ::core::option::Option, + /// The maximum known edition (inclusive) when this was constructed. Editions + /// after this will not have reliable defaults. + #[prost(enumeration = "Edition", optional, tag = "5")] + pub maximum_edition: ::core::option::Option, +} +/// Nested message and enum types in `FeatureSetDefaults`. +pub mod feature_set_defaults { + /// A map from every known edition with a unique set of defaults to its + /// defaults. Not all editions may be contained here. For a given edition, + /// the defaults at the closest matching edition ordered at or before it should + /// be used. This field must be in strict ascending order by edition. + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct FeatureSetEditionDefault { + #[prost(enumeration = "super::Edition", optional, tag = "3")] + pub edition: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub features: ::core::option::Option, + } +} /// Encapsulates information about the original source file from which a /// FileDescriptorProto was generated. #[allow(clippy::derive_partial_eq_without_eq)] @@ -1145,10 +1724,117 @@ pub mod generated_code_info { #[prost(int32, optional, tag = "3")] pub begin: ::core::option::Option, /// Identifies the ending offset in bytes in the generated code that - /// relates to the identified offset. The end offset should be one past + /// relates to the identified object. The end offset should be one past /// the last relevant byte (so the length of the text = end - begin). #[prost(int32, optional, tag = "4")] pub end: ::core::option::Option, + #[prost(enumeration = "annotation::Semantic", optional, tag = "5")] + pub semantic: ::core::option::Option, + } + /// Nested message and enum types in `Annotation`. + pub mod annotation { + /// Represents the identified object's effect on the element in the original + /// .proto file. + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum Semantic { + /// There is no effect or the effect is indescribable. + None = 0, + /// The element is set or otherwise mutated. + Set = 1, + /// An alias to the element is returned. + Alias = 2, + } + impl Semantic { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Semantic::None => "NONE", + Semantic::Set => "SET", + Semantic::Alias => "ALIAS", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "NONE" => Some(Self::None), + "SET" => Some(Self::Set), + "ALIAS" => Some(Self::Alias), + _ => None, + } + } + } + } +} +/// The full set of known editions. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum Edition { + /// A placeholder for an unknown edition value. + Unknown = 0, + /// Legacy syntax "editions". These pre-date editions, but behave much like + /// distinct editions. These can't be used to specify the edition of proto + /// files, but feature definitions must supply proto2/proto3 defaults for + /// backwards compatibility. + Proto2 = 998, + Proto3 = 999, + /// Editions that have been released. The specific values are arbitrary and + /// should not be depended on, but they will always be time-ordered for easy + /// comparison. + Edition2023 = 1000, + /// Placeholder editions for testing feature resolution. These should not be + /// used or relyed on outside of tests. + Edition1TestOnly = 1, + Edition2TestOnly = 2, + Edition99997TestOnly = 99997, + Edition99998TestOnly = 99998, + Edition99999TestOnly = 99999, +} +impl Edition { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Edition::Unknown => "EDITION_UNKNOWN", + Edition::Proto2 => "EDITION_PROTO2", + Edition::Proto3 => "EDITION_PROTO3", + Edition::Edition2023 => "EDITION_2023", + Edition::Edition1TestOnly => "EDITION_1_TEST_ONLY", + Edition::Edition2TestOnly => "EDITION_2_TEST_ONLY", + Edition::Edition99997TestOnly => "EDITION_99997_TEST_ONLY", + Edition::Edition99998TestOnly => "EDITION_99998_TEST_ONLY", + Edition::Edition99999TestOnly => "EDITION_99999_TEST_ONLY", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "EDITION_UNKNOWN" => Some(Self::Unknown), + "EDITION_PROTO2" => Some(Self::Proto2), + "EDITION_PROTO3" => Some(Self::Proto3), + "EDITION_2023" => Some(Self::Edition2023), + "EDITION_1_TEST_ONLY" => Some(Self::Edition1TestOnly), + "EDITION_2_TEST_ONLY" => Some(Self::Edition2TestOnly), + "EDITION_99997_TEST_ONLY" => Some(Self::Edition99997TestOnly), + "EDITION_99998_TEST_ONLY" => Some(Self::Edition99998TestOnly), + "EDITION_99999_TEST_ONLY" => Some(Self::Edition99999TestOnly), + _ => None, + } } } /// `Any` contains an arbitrary serialized protocol buffer message along with a @@ -1319,7 +2005,6 @@ pub struct Any { /// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) /// .setNanos((int) ((millis % 1000) * 1000000)).build(); /// -/// /// Example 5: Compute Timestamp from Java `Instant.now()`. /// /// Instant now = Instant.now(); @@ -1328,7 +2013,6 @@ pub struct Any { /// Timestamp.newBuilder().setSeconds(now.getEpochSecond()) /// .setNanos(now.getNano()).build(); /// -/// /// Example 6: Compute Timestamp from current time in Python. /// /// timestamp = Timestamp() @@ -1358,10 +2042,9 @@ pub struct Any { /// \[`strftime`\]() with /// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use /// the Joda Time's \[`ISODateTimeFormat.dateTime()`\]( -/// +/// ) /// ) to obtain a formatter capable of generating timestamps in this format. /// -/// #[derive(::serde::Serialize, ::serde::Deserialize)] #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -1437,7 +2120,6 @@ pub struct Timestamp { /// be expressed in JSON format as "3.000000001s", and 3 seconds and 1 /// microsecond should be expressed in JSON format as "3.000001s". /// -/// #[derive(::serde::Serialize, ::serde::Deserialize)] #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] diff --git a/proto/src/prost/ibc.lightclients.parlia.v1.rs b/proto/src/prost/ibc.lightclients.parlia.v1.rs index 0f35700..5be5614 100644 --- a/proto/src/prost/ibc.lightclients.parlia.v1.rs +++ b/proto/src/prost/ibc.lightclients.parlia.v1.rs @@ -43,6 +43,10 @@ pub struct Header { pub current_validators: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, #[prost(bytes = "vec", repeated, tag = "5")] pub previous_validators: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, + #[prost(uint32, tag = "6")] + pub current_turn_length: u32, + #[prost(uint32, tag = "7")] + pub previous_turn_length: u32, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)]