@@ -2,16 +2,19 @@ import { test, testProp, fc } from '@fast-check/ava';
22import { HashZero as zero } from '@ethersproject/constants' ;
33import { keccak256 } from '@ethersproject/keccak256' ;
44import { SimpleMerkleTree } from './simple' ;
5- import { BytesLike , HexString , concat , compare } from './bytes' ;
5+ import { BytesLike , HexString , concat , compare , toHex } from './bytes' ;
6+ import { InvalidArgumentError , InvariantError } from './utils/errors' ;
7+
8+ fc . configureGlobal ( { numRuns : process . env . CI ? 5000 : 100 } ) ;
69
710const reverseNodeHash = ( a : BytesLike , b : BytesLike ) : HexString => keccak256 ( concat ( [ a , b ] . sort ( compare ) . reverse ( ) ) ) ;
811const otherNodeHash = ( a : BytesLike , b : BytesLike ) : HexString => keccak256 ( reverseNodeHash ( a , b ) ) ; // double hash
912
10- import { toHex } from './bytes' ;
11- import { InvalidArgumentError , InvariantError } from './utils/errors' ;
12-
13- const leaf = fc . uint8Array ( { minLength : 32 , maxLength : 32 } ) . map ( toHex ) ;
14- const leaves = fc . array ( leaf , { minLength : 1 } ) ;
13+ // Use a mix of uint8array and hexstring to cover the Byteslike space
14+ const leaf = fc
15+ . uint8Array ( { minLength : 32 , maxLength : 32 } )
16+ . chain ( l => fc . oneof ( fc . constant ( l ) , fc . constant ( toHex ( l ) ) ) ) ;
17+ const leaves = fc . array ( leaf , { minLength : 1 , maxLength : 1000 } ) ;
1518const options = fc . record ( {
1619 sortLeaves : fc . oneof ( fc . constant ( undefined ) , fc . boolean ( ) ) ,
1720 nodeHash : fc . oneof ( fc . constant ( undefined ) , fc . constant ( reverseNodeHash ) ) ,
@@ -20,27 +23,31 @@ const options = fc.record({
2023const tree = fc
2124 . tuple ( leaves , options )
2225 . chain ( ( [ leaves , options ] ) => fc . tuple ( fc . constant ( SimpleMerkleTree . of ( leaves , options ) ) , fc . constant ( options ) ) ) ;
23- const treeAndLeaf = fc . tuple ( leaves , options ) . chain ( ( [ leaves , options ] ) =>
26+ const treeAndLeaf = tree . chain ( ( [ tree , options ] ) =>
2427 fc . tuple (
25- fc . constant ( SimpleMerkleTree . of ( leaves , options ) ) ,
28+ fc . constant ( tree ) ,
2629 fc . constant ( options ) ,
27- fc . nat ( { max : leaves . length - 1 } ) . map ( index => ( { value : leaves [ index ] ! , index } ) ) ,
30+ fc . nat ( { max : tree . length - 1 } ) . map ( index => ( { value : tree . at ( index ) ! , index } ) ) ,
2831 ) ,
2932) ;
30- const treeAndLeaves = fc . tuple ( leaves , options ) . chain ( ( [ leaves , options ] ) =>
33+ const treeAndLeaves = tree . chain ( ( [ tree , options ] ) =>
3134 fc . tuple (
32- fc . constant ( SimpleMerkleTree . of ( leaves , options ) ) ,
35+ fc . constant ( tree ) ,
3336 fc . constant ( options ) ,
3437 fc
35- . uniqueArray ( fc . nat ( { max : leaves . length - 1 } ) )
36- . map ( indices => indices . map ( index => ( { value : leaves [ index ] ! , index } ) ) ) ,
38+ . uniqueArray ( fc . nat ( { max : tree . length - 1 } ) )
39+ . map ( indices => indices . map ( index => ( { value : tree . at ( index ) ! , index } ) ) ) ,
3740 ) ,
3841) ;
3942
40- fc . configureGlobal ( { numRuns : process . env . CI ? 10000 : 100 } ) ;
41-
4243testProp ( 'generates a valid tree' , [ tree ] , ( t , [ tree ] ) => {
4344 t . notThrows ( ( ) => tree . validate ( ) ) ;
45+
46+ // check leaves enumeration
47+ for ( const [ index , value ] of tree . entries ( ) ) {
48+ t . is ( value , tree . at ( index ) ! ) ;
49+ }
50+ t . is ( tree . at ( tree . length ) , undefined ) ;
4451} ) ;
4552
4653testProp (
@@ -118,10 +125,14 @@ testProp('dump and load', [tree], (t, [tree, options]) => {
118125 const recoveredTree = SimpleMerkleTree . load ( dump , options . nodeHash ) ;
119126 recoveredTree . validate ( ) ; // already done in load
120127
128+ // check dump & reconstructed tree
129+ t . is ( dump . format , 'simple-v1' ) ;
121130 t . is ( dump . hash , options . nodeHash ? 'custom' : undefined ) ;
131+ t . true ( dump . values . every ( ( { value } , index ) => value === toHex ( tree . at ( index ) ! ) ) ) ;
132+ t . true ( dump . values . every ( ( { value } , index ) => value === toHex ( recoveredTree . at ( index ) ! ) ) ) ;
122133 t . is ( tree . root , recoveredTree . root ) ;
134+ t . is ( tree . length , recoveredTree . length ) ;
123135 t . is ( tree . render ( ) , recoveredTree . render ( ) ) ;
124- t . deepEqual ( tree . entries ( ) , recoveredTree . entries ( ) ) ;
125136 t . deepEqual ( tree . dump ( ) , recoveredTree . dump ( ) ) ;
126137} ) ;
127138
0 commit comments