merkle_tree.move 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. // Implementation of a Merkle tree in Move. Supports constructing a new tree
  2. // with a given depth, as well as proving that a leaf node belongs to the tree.
  3. module pyth::merkle_tree {
  4. use std::vector::{Self};
  5. use sui::hash::{keccak256};
  6. use wormhole::bytes20::{Self, Bytes20, data};
  7. use wormhole::cursor::Cursor;
  8. use pyth::deserialize::{Self};
  9. #[test_only]
  10. use wormhole::cursor::{Self};
  11. const MERKLE_LEAF_PREFIX: u8 = 0;
  12. const MERKLE_NODE_PREFIX: u8 = 1;
  13. const MERKLE_EMPTY_LEAF_PREFIX: u8 = 2;
  14. const E_DEPTH_NOT_LARGE_ENOUGH_FOR_MESSAGES: u64 = 1212121;
  15. // take keccak256 of input data, then return 20 leftmost bytes of result
  16. fun hash(bytes: &vector<u8>): Bytes20 {
  17. let hashed_bytes = keccak256(bytes);
  18. let hash_prefix = vector::empty<u8>();
  19. let i = 0;
  20. while (i < 20) {
  21. vector::push_back(&mut hash_prefix, *vector::borrow(&hashed_bytes, i));
  22. i = i + 1;
  23. };
  24. bytes20::new(hash_prefix)
  25. }
  26. fun empty_leaf_hash(): Bytes20 {
  27. let v = vector<u8>[MERKLE_EMPTY_LEAF_PREFIX];
  28. hash(&v)
  29. }
  30. fun leaf_hash(data: &vector<u8>): Bytes20 {
  31. let v = vector<u8>[MERKLE_LEAF_PREFIX];
  32. let i = 0;
  33. while (i < vector::length(data)) {
  34. vector::push_back(&mut v, *vector::borrow(data, i));
  35. i = i + 1;
  36. };
  37. hash(&v)
  38. }
  39. fun node_hash(
  40. childA: Bytes20,
  41. childB: Bytes20
  42. ): Bytes20 {
  43. if (greater_than(&childA, &childB)) {
  44. (childA, childB) = (childB, childA);
  45. };
  46. // append data_B to data_A
  47. let data_A = bytes20::data(&childA);
  48. let data_B = bytes20::data(&childB);
  49. // create a vector containing MERKLE_NODE_PREFIX + data_A + data_B
  50. let v = vector<u8>[MERKLE_NODE_PREFIX];
  51. let i = 0;
  52. while (i < 20) {
  53. vector::push_back(&mut v, *vector::borrow(&data_A, i));
  54. i = i + 1;
  55. };
  56. let i = 0;
  57. while (i < 20) {
  58. vector::push_back(&mut v, *vector::borrow(&data_B, i));
  59. i = i + 1;
  60. };
  61. hash(&v)
  62. }
  63. // greater_than returns whether a is strictly greater than b
  64. // note that data(&a) and data(&b) are both vector<u8>s of length 20
  65. fun greater_than(a: &Bytes20, b: &Bytes20): bool {
  66. // aa and bb both have length 20
  67. let a_vector = data(a);
  68. let b_vector = data(b);
  69. let i = 0;
  70. while (i < 20) {
  71. let a_value = *vector::borrow(&a_vector, i);
  72. let b_value = *vector::borrow(&b_vector, i);
  73. if (a_value > b_value) {
  74. return true
  75. } else if (b_value > a_value) {
  76. return false
  77. };
  78. i = i + 1;
  79. };
  80. false
  81. }
  82. // The Sui Move stdlb insert function shifts v[i] and subsequent elements to the right.
  83. // We don't want this behavior, so we define our own set_element function that instead replaces the ith element.
  84. // Reference: https://github.com/MystenLabs/sui/blob/main/crates/sui-framework/packages/move-stdlib/sources/vector.move
  85. fun set_element<T: drop>(a: &mut vector<T>, value: T, index: u64){
  86. vector::push_back<T>(a, value); // push value to end
  87. vector::swap_remove(a, index); // swap value to correct position and pop last value
  88. }
  89. // is_proof_valid returns whether a merkle proof is valid
  90. public fun is_proof_valid(
  91. encoded_proof: &mut Cursor<u8>,
  92. root: Bytes20,
  93. leaf_data: vector<u8>,
  94. ): bool {
  95. let current_digest: Bytes20 = leaf_hash(&leaf_data);
  96. let proofSize: u8 = deserialize::deserialize_u8(encoded_proof);
  97. while (proofSize > 0){
  98. let sibling_digest: Bytes20 = bytes20::new(
  99. deserialize::deserialize_vector(encoded_proof, 20)
  100. );
  101. current_digest = node_hash(
  102. current_digest,
  103. sibling_digest
  104. );
  105. proofSize = proofSize - 1;
  106. };
  107. bytes20::data(&current_digest) == bytes20::data(&root)
  108. }
  109. // construct_proofs constructs a merkle tree and returns the root of the tree as
  110. // a Bytes20 as well as the vector of encoded proofs
  111. public fun construct_proofs(
  112. messages: &vector<vector<u8>>,
  113. depth: u8
  114. ) : (Bytes20, vector<u8>) {
  115. if ( 1 << depth < vector::length(messages)) {
  116. abort E_DEPTH_NOT_LARGE_ENOUGH_FOR_MESSAGES
  117. };
  118. // empty tree
  119. // The tree is structured as follows:
  120. // 1
  121. // 2 3
  122. // 4 5 6 7
  123. // ...
  124. // In this structure the parent of node x is x//2 and the children
  125. // of node x are x*2 and x*2 + 1. Also, the sibling of the node x
  126. // is x^1. The root is at index 1 and index 0 is not used.
  127. let tree = vector::empty<Bytes20>();
  128. // empty leaf hash
  129. let cachedEmptyLeafHash: Bytes20 = empty_leaf_hash();
  130. // Instantiate tree to be a full binary tree with the appropriate depth.
  131. // Add an entry at the end for swapping
  132. let i: u64 = 0;
  133. while (i < (1 << (depth+1)) + 1){
  134. vector::push_back(&mut tree, cachedEmptyLeafHash);
  135. i = i + 1;
  136. };
  137. // Fill in bottom row with leaf hashes
  138. let j: u64 = 0;
  139. while (j < vector::length(messages)){
  140. set_element<Bytes20>(&mut tree, leaf_hash(vector::borrow(messages, j)), (1 << depth) + j);
  141. j = j + 1;
  142. };
  143. // Filling the node hashes from bottom to top
  144. let k: u8 = depth;
  145. while (k>0){
  146. let level: u8 = k-1;
  147. let levelNumNodes = 1 << level;
  148. let i: u64 = 0;
  149. while (i < levelNumNodes ){
  150. let id = (1 << level) + i;
  151. let node_hash = node_hash(*vector::borrow(&tree, id * 2), *vector::borrow(&tree, id * 2 + 1));
  152. set_element<Bytes20>(&mut tree, node_hash, id);
  153. i = i + 1;
  154. };
  155. k = k - 1;
  156. };
  157. let root = *vector::borrow(&tree, 1);
  158. // construct proofs and create encoded proofs vector
  159. let proofs = vector::empty<u8>();
  160. let i: u64 = 0;
  161. while (i < vector::length(messages)){
  162. let cur_proof = vector::empty<u8>();
  163. vector::push_back(&mut cur_proof, depth);
  164. let idx = (1 << depth) + i;
  165. while (idx > 1) {
  166. vector::append(&mut cur_proof, bytes20::data(vector::borrow(&tree, idx ^ 1)));
  167. // Jump to parent
  168. idx = idx / 2;
  169. };
  170. vector::append(&mut proofs, cur_proof);
  171. i = i + 1;
  172. };
  173. (root, proofs)
  174. }
  175. #[test]
  176. fun testGreaterThan(){
  177. // test 1
  178. let x = bytes20::new(x"0000000000000000000000000000000000001000");
  179. let y = bytes20::new(x"0000000000000000000000000000000000000001");
  180. let res = greater_than(&x, &y);
  181. assert!(res==true, 0);
  182. res = greater_than(&y, &x);
  183. assert!(res==false, 0);
  184. // test 2
  185. x = bytes20::new(x"1100000000000000000000000000000000001000");
  186. y = bytes20::new(x"1100000000000000000000000000000000000001");
  187. res = greater_than(&x, &y);
  188. assert!(res==true, 0);
  189. // equality case
  190. x = bytes20::new(x"1100000000000000000000000000000000001001");
  191. y = bytes20::new(x"1100000000000000000000000000000000001001");
  192. res = greater_than(&x, &y);
  193. assert!(res==false, 0);
  194. }
  195. #[test]
  196. fun test_hash_leaf() {
  197. let data: vector<u8> = x"00640000000000000000000000000000000000000000000000000000000000000000000000000000640000000000000064000000640000000000000064000000000000006400000000000000640000000000000064";
  198. let hash = leaf_hash(&data);
  199. let expected = bytes20::new(x"afc6a8ac466430f35895055f8a4c951785dad5ce");
  200. assert!(hash == expected, 1);
  201. }
  202. #[test]
  203. fun test_hash_node() {
  204. let h1 = bytes20::new(x"05c51b04b820c0f704e3fdd2e4fc1e70aff26dff");
  205. let h2 = bytes20::new(x"1e108841c8d21c7a5c4860c8c3499c918ea9e0ac");
  206. let hash = node_hash(h1, h2);
  207. let expected = bytes20::new(x"2d0e4fde68184c7ce8af426a0865bd41ef84dfa4");
  208. assert!(hash == expected, 1);
  209. }
  210. #[test]
  211. fun testMerkleTreeDepth1(){
  212. let messages = vector::empty<vector<u8>>();
  213. vector::push_back(&mut messages, x"1234");
  214. let (root, proofs) = construct_proofs(&messages, 1);
  215. let proofs_cursor = cursor::new(proofs);
  216. let valid = is_proof_valid(&mut proofs_cursor, root, x"1234");
  217. assert!(valid==true, 0);
  218. // destroy cursor
  219. cursor::take_rest<u8>(proofs_cursor);
  220. }
  221. #[test]
  222. fun testMerkleTreeDepth2(){
  223. let messages = vector::empty<vector<u8>>();
  224. vector::push_back(&mut messages, x"1234");
  225. vector::push_back(&mut messages, x"4321");
  226. vector::push_back(&mut messages, x"11");
  227. vector::push_back(&mut messages, x"22");
  228. let (root, proofs) = construct_proofs(&messages, 2);
  229. let proofs_cursor = cursor::new(proofs);
  230. assert!(is_proof_valid(&mut proofs_cursor, root, x"1234")==true, 0);
  231. assert!(is_proof_valid(&mut proofs_cursor, root, x"4321")==true, 0);
  232. assert!(is_proof_valid(&mut proofs_cursor, root, x"11")==true, 0);
  233. assert!(is_proof_valid(&mut proofs_cursor, root, x"22")==true, 0);
  234. // destroy cursor
  235. cursor::take_rest<u8>(proofs_cursor);
  236. }
  237. #[test]
  238. fun test_merkle_tree_depth_3(){
  239. let messages = vector::empty<vector<u8>>();
  240. vector::push_back(&mut messages, x"00");
  241. vector::push_back(&mut messages, x"4321");
  242. vector::push_back(&mut messages, x"444444");
  243. vector::push_back(&mut messages, x"22222222");
  244. vector::push_back(&mut messages, x"22");
  245. vector::push_back(&mut messages, x"11");
  246. vector::push_back(&mut messages, x"100000");
  247. vector::push_back(&mut messages, x"eeeeee");
  248. let (root, proofs) = construct_proofs(&messages, 3);
  249. let proofs_cursor = cursor::new(proofs);
  250. assert!(is_proof_valid(&mut proofs_cursor, root, x"00")==true, 0);
  251. assert!(is_proof_valid(&mut proofs_cursor, root, x"4321")==true, 0);
  252. assert!(is_proof_valid(&mut proofs_cursor, root, x"444444")==true, 0);
  253. assert!(is_proof_valid(&mut proofs_cursor, root, x"22222222")==true, 0);
  254. assert!(is_proof_valid(&mut proofs_cursor, root, x"22")==true, 0);
  255. assert!(is_proof_valid(&mut proofs_cursor, root, x"11")==true, 0);
  256. assert!(is_proof_valid(&mut proofs_cursor, root, x"100000")==true, 0);
  257. assert!(is_proof_valid(&mut proofs_cursor, root, x"eeeeee")==true, 0);
  258. // destroy cursor
  259. cursor::take_rest<u8>(proofs_cursor);
  260. }
  261. #[test]
  262. fun test_merkle_tree_depth_1_invalid_proofs(){
  263. let messages = vector::empty<vector<u8>>();
  264. vector::push_back(&mut messages, x"1234");
  265. let (root, proofs) = construct_proofs(&messages, 1);
  266. let proofs_cursor = cursor::new(proofs);
  267. // use wrong leaf data (it is not included in the tree)
  268. let valid = is_proof_valid(&mut proofs_cursor, root, x"432222");
  269. assert!(valid==false, 0);
  270. // destroy cursor
  271. cursor::take_rest<u8>(proofs_cursor);
  272. }
  273. #[test]
  274. fun test_merkle_tree_depth_2_invalid_proofs(){
  275. let messages = vector::empty<vector<u8>>();
  276. vector::push_back(&mut messages, x"1234");
  277. vector::push_back(&mut messages, x"4321");
  278. vector::push_back(&mut messages, x"11");
  279. vector::push_back(&mut messages, x"22");
  280. let (root, proofs) = construct_proofs(&messages, 2);
  281. let proofs_cursor = cursor::new(proofs);
  282. // proof fails because we used the proof of x"1234" to try to prove that x"4321" is in the tree
  283. assert!(is_proof_valid(&mut proofs_cursor, root, x"4321")==false, 0);
  284. // proof succeeds
  285. assert!(is_proof_valid(&mut proofs_cursor, root, x"4321")==true, 0);
  286. // proof fails because we used the proof of x"11" to try to prove that x"22" is in the tree
  287. assert!(is_proof_valid(&mut proofs_cursor, root, x"22")==false, 0);
  288. // proof succeeds
  289. assert!(is_proof_valid(&mut proofs_cursor, root, x"22")==true, 0);
  290. // destroy cursor
  291. cursor::take_rest<u8>(proofs_cursor);
  292. }
  293. #[test]
  294. fun test_merkle_tree_depth_3_invalid_proofs(){
  295. let messages = vector::empty<vector<u8>>();
  296. vector::push_back(&mut messages, x"00");
  297. vector::push_back(&mut messages, x"4321");
  298. vector::push_back(&mut messages, x"444444");
  299. vector::push_back(&mut messages, x"22222222");
  300. vector::push_back(&mut messages, x"22");
  301. vector::push_back(&mut messages, x"11");
  302. vector::push_back(&mut messages, x"100000");
  303. vector::push_back(&mut messages, x"eeeeee");
  304. let (root, proofs) = construct_proofs(&messages, 3);
  305. let proofs_cursor = cursor::new(proofs);
  306. // test various proof failure cases (because of mismatch between proof and leaf data)
  307. assert!(is_proof_valid(&mut proofs_cursor, root, x"00")==true, 0);
  308. assert!(is_proof_valid(&mut proofs_cursor, root, x"22")==false, 0);
  309. assert!(is_proof_valid(&mut proofs_cursor, root, x"22222222")==false, 0);
  310. assert!(is_proof_valid(&mut proofs_cursor, root, x"22222222")==true, 0);
  311. assert!(is_proof_valid(&mut proofs_cursor, root, x"22")==true, 0);
  312. assert!(is_proof_valid(&mut proofs_cursor, root, x"eeeeee")==false, 0);
  313. assert!(is_proof_valid(&mut proofs_cursor, root, x"4321")==false, 0);
  314. assert!(is_proof_valid(&mut proofs_cursor, root, x"eeeeee")==true, 0);
  315. // destroy cursor
  316. cursor::take_rest<u8>(proofs_cursor);
  317. }
  318. #[test]
  319. #[expected_failure(abort_code = pyth::merkle_tree::E_DEPTH_NOT_LARGE_ENOUGH_FOR_MESSAGES)]
  320. fun test_merkle_tree_depth_exceeded_1(){
  321. let messages = vector::empty<vector<u8>>();
  322. vector::push_back(&mut messages, x"00");
  323. vector::push_back(&mut messages, x"4321");
  324. vector::push_back(&mut messages, x"444444");
  325. construct_proofs(&messages, 1); //depth 1
  326. }
  327. #[test]
  328. #[expected_failure(abort_code = pyth::merkle_tree::E_DEPTH_NOT_LARGE_ENOUGH_FOR_MESSAGES)]
  329. fun test_merkle_tree_depth_exceeded_2(){
  330. let messages = vector::empty<vector<u8>>();
  331. vector::push_back(&mut messages, x"00");
  332. vector::push_back(&mut messages, x"4321");
  333. vector::push_back(&mut messages, x"444444");
  334. vector::push_back(&mut messages, x"22222222");
  335. vector::push_back(&mut messages, x"22");
  336. construct_proofs(&messages, 2); // depth 2
  337. }
  338. }