2727//! Merkle Tree is constructed from arbitrary-length leaves, that are initially hashed using the
2828//! same hasher as the inner nodes.
2929//! Inner nodes are created by concatenating child hashes and hashing again. The implementation
30- //! does not perform any sorting of the input data (leaves) nor when inner nodes are created.
30+ //! sorts each pair of hashes before every hash operation. This makes proof verification more
31+ //! efficient by removing the need to track which side each intermediate hash is concatenated on.
3132//!
3233//! If the number of leaves is not even, last leaf (hash of) is promoted to the upper layer.
3334
@@ -45,7 +46,7 @@ use beefy_primitives::mmr::{BeefyAuthoritySet, BeefyNextAuthoritySet};
4546pub fn merkle_root < H , I > ( leaves : I ) -> H :: Output
4647where
4748 H : HashT ,
48- H :: Output : Default + AsRef < [ u8 ] > ,
49+ H :: Output : Default + AsRef < [ u8 ] > + PartialOrd ,
4950 I : IntoIterator ,
5051 I :: Item : AsRef < [ u8 ] > ,
5152{
5657fn merkelize < H , V , I > ( leaves : I , visitor : & mut V ) -> H :: Output
5758where
5859 H : HashT ,
59- H :: Output : Default + AsRef < [ u8 ] > ,
60+ H :: Output : Default + AsRef < [ u8 ] > + PartialOrd ,
6061 V : Visitor < H :: Output > ,
6162 I : Iterator < Item = H :: Output > ,
6263{
@@ -141,7 +142,7 @@ impl<T> Visitor<T> for () {
141142pub fn merkle_proof < H , I , T > ( leaves : I , leaf_index : usize ) -> MerkleProof < H :: Output , T >
142143where
143144 H : HashT ,
144- H :: Output : Default + Copy + AsRef < [ u8 ] > ,
145+ H :: Output : Default + Copy + AsRef < [ u8 ] > + PartialOrd ,
145146 I : IntoIterator < Item = T > ,
146147 I :: IntoIter : ExactSizeIterator ,
147148 T : AsRef < [ u8 ] > ,
@@ -241,7 +242,7 @@ pub fn verify_proof<'a, H, P, L>(
241242) -> bool
242243where
243244 H : HashT ,
244- H :: Output : PartialEq + AsRef < [ u8 ] > ,
245+ H :: Output : PartialEq + AsRef < [ u8 ] > + PartialOrd ,
245246 P : IntoIterator < Item = H :: Output > ,
246247 L : Into < Leaf < ' a , H :: Output > > ,
247248{
@@ -256,15 +257,13 @@ where
256257
257258 let hash_len = <H as sp_core:: Hasher >:: LENGTH ;
258259 let mut combined = vec ! [ 0_u8 ; hash_len * 2 ] ;
259- let mut position = leaf_index;
260- let mut width = number_of_leaves;
261260 let computed = proof. into_iter ( ) . fold ( leaf_hash, |a, b| {
262- if position % 2 == 1 || position + 1 == width {
263- combined[ ..hash_len] . copy_from_slice ( & b. as_ref ( ) ) ;
264- combined[ hash_len..] . copy_from_slice ( & a. as_ref ( ) ) ;
265- } else {
261+ if a < b {
266262 combined[ ..hash_len] . copy_from_slice ( & a. as_ref ( ) ) ;
267263 combined[ hash_len..] . copy_from_slice ( & b. as_ref ( ) ) ;
264+ } else {
265+ combined[ ..hash_len] . copy_from_slice ( & b. as_ref ( ) ) ;
266+ combined[ hash_len..] . copy_from_slice ( & a. as_ref ( ) ) ;
268267 }
269268 let hash = <H as HashT >:: hash ( & combined) ;
270269 #[ cfg( feature = "debug" ) ]
@@ -275,8 +274,6 @@ where
275274 array_bytes:: bytes2hex( "" , & hash. as_ref( ) ) ,
276275 array_bytes:: bytes2hex( "" , & combined. as_ref( ) )
277276 ) ;
278- position /= 2 ;
279- width = ( ( width - 1 ) / 2 ) + 1 ;
280277 hash
281278 } ) ;
282279
@@ -295,7 +292,7 @@ fn merkelize_row<H, V, I>(
295292) -> Result < H :: Output , Vec < H :: Output > >
296293where
297294 H : HashT ,
298- H :: Output : AsRef < [ u8 ] > ,
295+ H :: Output : AsRef < [ u8 ] > + PartialOrd ,
299296 V : Visitor < H :: Output > ,
300297 I : Iterator < Item = H :: Output > ,
301298{
@@ -321,8 +318,13 @@ where
321318 index += 2 ;
322319 match ( a, b) {
323320 ( Some ( a) , Some ( b) ) => {
324- combined[ ..hash_len] . copy_from_slice ( a. as_ref ( ) ) ;
325- combined[ hash_len..] . copy_from_slice ( b. as_ref ( ) ) ;
321+ if a < b {
322+ combined[ ..hash_len] . copy_from_slice ( a. as_ref ( ) ) ;
323+ combined[ hash_len..] . copy_from_slice ( b. as_ref ( ) ) ;
324+ } else {
325+ combined[ ..hash_len] . copy_from_slice ( b. as_ref ( ) ) ;
326+ combined[ hash_len..] . copy_from_slice ( a. as_ref ( ) ) ;
327+ }
326328
327329 next. push ( <H as HashT >:: hash ( & combined) ) ;
328330 } ,
@@ -428,12 +430,12 @@ mod tests {
428430 } ;
429431
430432 test (
431- "aff1208e69c9e8be9b584b07ebac4e48a1ee9d15ce3afe20b77a4d29e4175aa3 " ,
433+ "5842148bc6ebeb52af882a317c765fccd3ae80589b21a9b8cbf21abb630e46a7 " ,
432434 vec ! [ "a" , "b" , "c" ] ,
433435 ) ;
434436
435437 test (
436- "b8912f7269068901f231a965adfefbc10f0eedcfa61852b103efd54dac7db3d7 " ,
438+ "7b84bec68b13c39798c6c50e9e40a0b268e3c1634db8f4cb97314eb243d4c514 " ,
437439 vec ! [ "a" , "b" , "a" ] ,
438440 ) ;
439441
@@ -443,7 +445,7 @@ mod tests {
443445 ) ;
444446
445447 test (
446- "fb3b3be94be9e983ba5e094c9c51a7d96a4fa2e5d8e891df00ca89ba05bb1239 " ,
448+ "cc50382cfd3c9a617741e9a85efee8752b8feb95a2cbecd6365fb21366ce0c8c " ,
447449 vec ! [ "a" , "b" , "c" , "d" , "e" , "f" , "g" , "h" , "i" , "j" ] ,
448450 ) ;
449451 }
@@ -761,7 +763,7 @@ mod tests {
761763 "0xc26B34D375533fFc4c5276282Fa5D660F3d8cbcB" ,
762764 ] ;
763765 let root: H256 = array_bytes:: hex2array_unchecked (
764- "72b0acd7c302a84f1f6b6cefe0ba7194b7398afb440e1b44a9dbbe270394ca53 " ,
766+ "7b2c6eebec6e85b2e272325a11c31af71df52bc0534d2d4f903e0ced191f022e " ,
765767 )
766768 . into ( ) ;
767769
@@ -806,11 +808,11 @@ mod tests {
806808 )
807809 . into( ) ,
808810 array_bytes:: hex2array_unchecked(
809- "d02609d2bbdb28aa25f58b85afec937d5a4c85d37925bce6d0cf802f9d76ba79 "
811+ "1fad92ed8d0504ef6c0231bbbeeda960a40693f297c64e87b582beb92ecfb00f "
810812 )
811813 . into( ) ,
812814 array_bytes:: hex2array_unchecked(
813- "ae3f8991955ed884613b0a5f40295902eea0e0abe5858fc520b72959bc016d4e "
815+ "0b84c852cbcf839d562d826fd935e1b37975ccaa419e1def8d219df4b83dcbf4 "
814816 )
815817 . into( ) ,
816818 ] ,
0 commit comments