From 114a9296d7fec39f1e5a3a8e85f14bfff723c71d Mon Sep 17 00:00:00 2001 From: tiagofneto Date: Thu, 2 Nov 2023 11:31:04 +0600 Subject: [PATCH] fix: mpt verification overflowing for long key_end and shared_nibbles --- src/data_structures/eth_mpt.cairo | 76 +++++++++++--------- src/data_structures/tests/test_eth_mpt.cairo | 55 ++++++++++++++ 2 files changed, 98 insertions(+), 33 deletions(-) diff --git a/src/data_structures/eth_mpt.cairo b/src/data_structures/eth_mpt.cairo index 7733a79..e56c9ec 100644 --- a/src/data_structures/eth_mpt.cairo +++ b/src/data_structures/eth_mpt.cairo @@ -148,37 +148,42 @@ impl MPTImpl of MPTTrait { let mut shared_nibbles_word_idx = nibbles_skip / 16; let mut shared_nibbles_word = *shared_nibbles.at(shared_nibbles_word_idx); let mut i_nibbles = 0; - let next_hash = loop { - if i_nibbles == n_nibbles { - break Result::Ok(next_node); - } - if key_pow2 == 0 { - break Result::Err('Key reached end'); - } + let next_hash = if n_nibbles == 0 { + Result::Ok(next_node) + } else { + loop { + let current_nibble_shared_nibbles = (shared_nibbles_word + / shared_nibbles_pow2) + & 0xf; + let current_nibble_key = (key / key_pow2) & 0xf; + if current_nibble_shared_nibbles.into() != current_nibble_key { + break Result::Err('Extension nibbles not matching'); + } - let current_nibble_shared_nibbles = (shared_nibbles_word - / shared_nibbles_pow2) - & 0xf; - let current_nibble_key = (key / key_pow2) & 0xf; - if current_nibble_shared_nibbles.into() != current_nibble_key { - break Result::Err('Extension nibbles not matching'); - } + key_pow2 = key_pow2 / 16; + i_nibbles += 1; - if shared_nibbles_pow2 == 0x100000000000000 { - shared_nibbles_pow2 = 16; - shared_nibbles_word_idx += 1; - shared_nibbles_word = *shared_nibbles.at(shared_nibbles_word_idx); - } else { - if in_byte { - shared_nibbles_pow2 = shared_nibbles_pow2 * 0x1000; - } else { - shared_nibbles_pow2 = shared_nibbles_pow2 / 0x10; + if i_nibbles == n_nibbles { + break Result::Ok(next_node); + } + if key_pow2 == 0 { + break Result::Err('Key reached end'); } - }; - in_byte = !in_byte; - key_pow2 = key_pow2 / 16; - i_nibbles += 1; + if shared_nibbles_pow2 == 0x100000000000000 { + shared_nibbles_pow2 = 16; + shared_nibbles_word_idx += 1; + shared_nibbles_word = *shared_nibbles.at(shared_nibbles_word_idx); + } else { + if in_byte { + shared_nibbles_pow2 = shared_nibbles_pow2 * 0x1000; + } else { + shared_nibbles_pow2 = shared_nibbles_pow2 / 0x10; + } + }; + + in_byte = !in_byte; + } }; match next_hash { @@ -193,6 +198,10 @@ impl MPTImpl of MPTTrait { MPTNode::Leaf(( key_end, value, nibbles_skip, n_nibbles )) => { + if key_pow2 == 0 && n_nibbles == 0 { + break Result::Ok(value); + } + let mut key_end_pow2 = pow(2, nibbles_skip.into() * 4); let mut in_byte = false; @@ -209,16 +218,19 @@ impl MPTImpl of MPTTrait { let mut key_end_word = *key_end.at(key_end_word_idx); let mut i_nibbles = 0; break loop { - if key_pow2 == 0 && i_nibbles == n_nibbles { - break Result::Ok(value); - } - let current_nibble_key_end = (key_end_word / key_end_pow2) & 0xf; let current_nibble_key = (key / key_pow2) & 0xf; if current_nibble_key_end.into() != current_nibble_key { break Result::Err('Key not matching'); } + key_pow2 = key_pow2 / 16; + i_nibbles += 1; + + if key_pow2 == 0 && i_nibbles == n_nibbles { + break Result::Ok(value); + } + if key_end_pow2 == 0x100000000000000 { key_end_pow2 = 16; key_end_word_idx += 1; @@ -232,8 +244,6 @@ impl MPTImpl of MPTTrait { }; in_byte = !in_byte; - key_pow2 = key_pow2 / 16; - i_nibbles += 1; }; } }; diff --git a/src/data_structures/tests/test_eth_mpt.cairo b/src/data_structures/tests/test_eth_mpt.cairo index 42556d5..0d81dfe 100644 --- a/src/data_structures/tests/test_eth_mpt.cairo +++ b/src/data_structures/tests/test_eth_mpt.cairo @@ -1,5 +1,6 @@ use cairo_lib::data_structures::eth_mpt::{MPTNode, MPTTrait}; use cairo_lib::utils::types::words64::{Words64, Words64Trait}; +use debug::PrintTrait; #[test] #[available_gas(9999999999)] @@ -768,3 +769,57 @@ fn test_full_verify() { let res = mpt.verify(key, 64, proof.span()).unwrap(); assert(res == expected_res.span(), 'Result not matching'); } + +#[test] +#[available_gas(9999999999999)] +fn test_full_verify_2_nodes() { + //// Account : 0x7b5C526B7F8dfdff278b4a3e045083FBA4028790 | Goerli | Block 9000000 + ////"0xf90211a0f09eae4e1e51fdde02a2884e285b8a8a9c72cc7e7cdaeef013714e3499bcd475a0ce33fd7097055e50d64c42759027e41ffb22d5b2a03ee67207dc94b547e40956a04817bf75497b71a78957ff89d05107cbf16ead02f7e68f13cead9e7d24dfcda5a00751841dcd0e21ff273930aa4722cabae7ea4e09d0f4e9f667b57ab68a41652ea047008ee2caeec1839c016d0a8efd2e901091bfae5388fc064db9f14f4bda362da0f952be9637ec6790bcdcf9ae3d4bca607259f26c0731e3cbd2882924c9db5653a061a8882bde126643739fe5f0acc5d234467718c27217f56513fd222009802336a061dbaa68a4290e8cce57166ffc6fd22d081c5893a081082b23668ef6c7d65c81a0ef2e0aea160700e14be7285c8b83535f4d104a74ac8db6c188d84ee48a8a647ca0c00853c7500db3c616d5d7dcd7503c02307045e7670a0749ffdebadc732a9ab4a068050da8f891b57fbeacffe4ba3e41f11c5d6b0ec8553fbb796f46951ecd1445a0762e36c38c548c5ae61da51205ef1dc66390702397becef53c50d969cae7a2ada0abff9de80f8e14979ebbe80ae3e702e61b31b91ea481c0e63a7bde12e866eeb5a017220448de88495fdf81446233768ef9441058e4602ecafc1da85a7cbbf1c16da084351381e6cad5052c82f731e8d19d86193794eccdf274529bed7e67309cca78a0784e83133c0ba8ff0262d0c96dc93f936d97eac46327d32f3c1baceb63934d9d80", + ////"0xf90211a0679ec41f2230e1f57eededf17732966880d9835d744ad769a1b246829341a588a09c2941acea1f1461a7d0af3bb9917c16e3a3339556623a6cad6d1f40ee8fc8a8a0211b79624826f8cd651f7a0123356cfef56854adf7285163988ba4eee0e8f964a062a3e341692078b717029cd105b462749386aecc1cb647721cc382872eac4a51a01a9fc7658bcc2948e1123273e83fb66894e64c2e19aa8f3ac546c45ef4b22290a08c5cdf2e341821e9c3163ec52847e33884f4797669607a60a8adafd00edead0ea08b07046b12762a58e03a482d597cca869aaffd85214bbd08c4624325a7cf80c9a0602d16a56550182218f642f56e66b1cf72555c38dac0fd061b8ef113d4653f4aa038fa2d962cfe43eb49f5a7d1787a436e8e3c6858665b1b0703c4e42ad43f962ea03a706c9b0e0757079f96d9df003eae31aafcf7525d6114033ee929c78adc580aa0f8a66bdc97088d4c73429b9ee00d7bcd0589be3462a53e9f5b9876d4b5231e40a04bbcbff81f2c0b65f29724ef71f6d439b6f857ad5fa7b643c1ea5dfc72ee240fa098cd5bf5aea320986616ff7bfc78efdf43091610fb457447058958e68a13e49ba02033016a2ef0512c926211fbec6f9b7398c58ae10116901d086905979649d968a07cf13191df973971dd4592a95c33cc3c248a4e919b8866c7c8ecff44a6e453a2a017010b7ff49cf72fbc13136f189457a2bc09e8c400ca9cb7997ff75bf34637ec80", + ////"0xf90211a06c86eef3a8754d952a265132ed86282d34ec24f9f5aa2f085629155798975c2ba02cef7b79076bddfe220fd88ca1a18414683b2f37e8b94cf8c6bdf743cff9d18ca00fe6e40f33bc1b76e34a6c92cdfce9b08f808bca7c6fe85348a7b7e838632a20a0f2f4d7b6fb649794a45288bfbc32274f3031ebc8bbf808146a3104ea27d72e7aa0cf2a353bb32b3b9c004c7586d6723ea5e2ccb99972c84b4b2c90166ca0c3c65ba0753fee595b7a0b80d3574db4e4615a599da7bedfa71bcb9ba214192c6dfb8a4fa0a7e45064974417eeef5556e4fa3533c819cc04825a33f0e244440d4d6a42828ca06cb2eaf789a62824a4a2b730bc4b8ee70e3648fbdf6cd61ea86d234dda67ccc3a0e42e79aeed163de73664c3b4f9451208b22b4874eae6c007b5f0405a64a55050a072f87da9fbd3c727080eef39891888876cdfbc54b732cf4f08ee19d067117d5ba0ce88e695612d636a6f73c2fcc0086e486249a0284cd6b88bf1cc3a7bef84ce9ba0d408599a558fc0ad84aba0bea36e00c1e99ddebf7b74e2f68912563bd5a62522a0154aef7de9275d13e860b11f138a811e6ed97fbf8985c524ccd5c231dbc62180a0282022799ec74b1dc2df4edad584b0b974113a06a857ff72ed17471908d28404a00c4fc7a3f7ded56f4da7093a875bd7c3a6cb35cc6bdf505cb79aee64708640aca0339829e86f4b7a2d68fe0b4707e32016534cdf8a48070a3921a48bcc0fd4b11c80", + ////"0xf90211a0b70bd38b197882c9e04dbdbc463bd74887af466e509bb9f61283796000649611a05b7c13208dc2fbd708005d510297a825e6ee16a541a1f7860b5226f39e7d31ada09fea01b1db9afdd63932fc4a335ca3af6824afcba793fab68a6536e4f302fc19a0d73148886a70f18c6a41f65a9d012b8a5198deacf33b0839b494a1338b23cf7ba0e6923675583267b502e2a6ac685651f4bfb54b6cf00cffdf7e603927107eca70a01e2fcb240f26a1d85e908bc77a75628b144f31b0f6d56ddc139cb5a56002420ca021420c0d6ab2d50504f7cad0e4d76109c2c93f2c49c9677863f290c8dc4e3c14a0379fe1bd0b044c94f67f844bd2c7f7abf83ac8049ab234ce301326d79fb7ae0ba0890ea9c4679262b86e65f2895ff9e6e97a0ed06d7beb9b4d3d8c8d3246a06715a04569c16e7ba91a901aec96cd999b89201e192670edaff70d2991edf779de5082a0adaed327e31819a530e941a4eebf0ed8e245b9272947199566e89e4496a6c05ba0c39e54b4ce440fbc36c43baafc9809a80e8cc5649b2f8753b5edbac3b7c043e3a0812541bed009f7cae97ba783dde88aced6e5f21fc80b41e91b9479d35184e45ea0708adda1f1ad89034e35a2fd063420d885713fb7f176960e47eebc0df8e8afc0a0a305e0528d3f6122a460eeffc54ce1c4c67f71f376e8d84a4ed23dfdc2cc4effa02928ce112a3e076214a2b1e25fbfc463411c378c12702506c1479f97ba5bffce80", + ////"0xf90211a09881800af81281b599a2ae599789501c2561294aeb892905e5f454bdcf79a187a047e8fd36ef03ad0479902154249d5e43071efbf78b4974f2cda490fa42d17ba6a063b7d25d086bdfa18c5beb67e4339f683de15346ef948b01139d8c0e83a96387a0b8662c97a229aa73ab190ab402a7fa2acad9cf66251ad0a44c9070732e298b11a0fac6584c1fa6aa7db2e615e10ba63a9b353f3febbe93d3ae2276891668aa7fc1a0777e0f4f2695a65939c8a191cc32e0bc74c557d057a46b5135f36e3c232b7fb8a0d78ec39c3544f76d77c0aa20b4cdb58c8ac29745713b240b7fdd3836497fdb04a04729097a95f6c001478b2ed057c71a9de89b0e4ee18cbf6c04d578bac2c7ed28a09f6f37e1ffed0554f4133b5743e4e7e807054ce7f9615df1fdcceb0264e31829a0cddde78e2ed07fd82b486cca326ec315f3d1df4a635f1898811b1d4d45d7361ca018f06484f8a256a810fdf6800d30c40094de7561a12b3cc9a9e90979e0ce4a10a08c01dbe66e1e60f5edea0e1bf2990aed610dadb9783f2070b206c88ffc05e7ffa09763ea84f4ae07ffec150a3d59674a49c944dc94409881b0380a3ed2e4ab6b70a0d0e86e1c6f991a9afb97bf1648487fcc90f61d4a6f7d8fa419cb829e11c5b764a042d00184633bd8df55db881b1b46457f1d0cff162c8843f9aea18509271f9407a081aad7099cafddcb44141737b986eec45e93aa16774c7d0480d395fca582cf8d80", + ////"0xf9019180a08eeac7bec8ceaaf659b328d4a04e418159914c7681f83470cd313d6e984a0754a06dac15ddea9fe0ba3097f94727c1f61cda2219e639c443e52b231ceb71b9c86fa0a6545f791304f8f4dfa8bae7699aff682733b246c6df78b03a955b87e974a330a0f75c6a10796830946f04645d5d11e5b0bcbc40f0cb83cd716440e6ef1d8b3d048080a0646d1cbea060b31a3ddfcb8e802620232a2164a64abc04dba88654667668261ba0c61e9aff13ad27a1d50510f88ff4879db3fd7cef1782982d3cf8702742b2941da0b2a8722ff78f03327b585da064ed79ea1818cff6cc41fe3249368cc04493ca41a001719ecf3a6e924abbdbb6f3de50794df3d9f9f503bfb54bab753e2d9b5c7230a08073f6a9ebd0c84a9dd5b6176d52bc80596eb74c192a7a551b3ae80620facaf7a0290f29ddbba5a789b068535aeda99809053bea7642e0bd7a604a15112b5818cb80a00bf0a7e8a9b0797f99bccaa5655462c00172c769c5bed589c149df04c9d748bfa02c83d167a8b35607906f4639c2442bacde5c67dab80bb2fc74564a32d3a3194380", + ////"0xf8679e20eb3d3905f6526cb7fbb8ca13df8d9c63efade348e70065aa05f578f315b846f8440180a06968aa4d96a817eb4d24aa4d096d0d841f9c52ed7bbc4ca7d7951bba6fc65571a089b1de4a1e012d6a62b18b6ad184985d57545bf1da0ae1c218f4cea34daf099b" + + let proof = array![ + array![ + 0x5c0b6aa0808051f8, + 0x9720a2845ec292e7, + 0xdde909402854fc40, + 0x8b0ff9103babb578, + 0x808080c17ea1cc35, + 0xf86ba08080808080, + 0x652dee110f0a9fd1, + 0x98195bc1e2e398a8, + 0xcb959918a8d08b95, + 0x8080d2e4ec07dcfc, + 0x808080 + ].span(), + array![ + 0x76522d0e31a043f8, + 0x71fdcdee263b0712, + 0xfa4a4bf40c326a7e, + 0xb7e2cb9f2d73b0c2, + 0x636f4da0a1f60cfa, + 0x000000000000006b, + 0x0000000000000000, + 0x0000000000000000, + 0x0800000000 + ].span() + ]; + + let expected_res = array![ + 0x6b636f4da0, + 0x0, + 0x0, + 0x0, + 0x8 + ]; + + let key = 0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6; + + let mpt = MPTTrait::new(0x8051DC27EC55E8B88C99B97B08DFF3E99B5106E4BED472E53B9B7D53C0129A6E); + let res = mpt.verify(key, 64, proof.span()).unwrap(); + assert(res == expected_res.span(), 'Result not matching'); +}