@@ -4,29 +4,36 @@ import (
4
4
"bytes"
5
5
"crypto/sha256"
6
6
"math/rand"
7
- "reflect"
8
7
"testing"
9
8
)
10
9
10
+ type opCounts struct { ops , inserts , updates , deletes int }
11
+ type bulkop struct { key , val []byte }
12
+
11
13
// Test all tree operations in bulk.
12
- func TestSparseMerkleTree (t * testing.T ) {
13
- for i := 0 ; i < 5 ; i ++ {
14
+ func TestBulkOperations (t * testing.T ) {
15
+ rand .Seed (1 )
16
+
17
+ cases := []opCounts {
14
18
// Test more inserts/updates than deletions.
15
- bulkOperations (t , 200 , 100 , 100 , 50 )
16
- }
17
- for i := 0 ; i < 5 ; i ++ {
19
+ {200 , 100 , 100 , 50 },
20
+ {1000 , 100 , 100 , 50 },
18
21
// Test extreme deletions.
19
- bulkOperations (t , 200 , 100 , 100 , 500 )
22
+ {200 , 100 , 100 , 500 },
23
+ {1000 , 100 , 100 , 500 },
24
+ }
25
+ for _ , tc := range cases {
26
+ bulkOperations (t , tc .ops , tc .inserts , tc .updates , tc .deletes )
20
27
}
21
28
}
22
29
23
30
// Test all tree operations in bulk, with specified ratio probabilities of insert, update and delete.
24
31
func bulkOperations (t * testing.T , operations int , insert int , update int , delete int ) {
25
32
smn , smv := NewSimpleMap (), NewSimpleMap ()
26
- smt := NewSparseMerkleTree (smn , smv , sha256 .New ())
33
+ smt := NewSMTWithStorage (smn , smv , sha256 .New ())
27
34
28
35
max := insert + update + delete
29
- kv := make ( map [ string ] string )
36
+ var kv [] bulkop
30
37
31
38
for i := 0 ; i < operations ; i ++ {
32
39
n := rand .Intn (max )
@@ -39,98 +46,90 @@ func bulkOperations(t *testing.T, operations int, insert int, update int, delete
39
46
val := make ([]byte , valLen )
40
47
rand .Read (val )
41
48
42
- kv [string (key )] = string (val )
43
- _ , err := smt .Update (key , val )
49
+ err := smt .Update (key , val )
44
50
if err != nil {
45
- t .Errorf ("error: %v" , err )
51
+ t .Fatalf ("error: %v" , err )
46
52
}
53
+ kv = append (kv , bulkop {key , val })
47
54
} else if n > insert && n < insert + update { // Update
48
- keys := reflect .ValueOf (kv ).MapKeys ()
49
- if len (keys ) == 0 {
55
+ if len (kv ) == 0 {
50
56
continue
51
57
}
52
- key := []byte (keys [rand .Intn (len (keys ))].Interface ().(string ))
53
-
58
+ ki := rand .Intn (len (kv ))
54
59
valLen := 1 + rand .Intn (64 )
55
60
val := make ([]byte , valLen )
56
61
rand .Read (val )
57
62
58
- kv [string (key )] = string (val )
59
- _ , err := smt .Update (key , val )
63
+ err := smt .Update (kv [ki ].key , val )
60
64
if err != nil {
61
- t .Errorf ("error: %v" , err )
65
+ t .Fatalf ("error: %v" , err )
62
66
}
67
+ kv [ki ].val = val
63
68
} else { // Delete
64
- keys := reflect .ValueOf (kv ).MapKeys ()
65
- if len (keys ) == 0 {
69
+ if len (kv ) == 0 {
66
70
continue
67
71
}
68
- key := [] byte ( keys [ rand .Intn (len (keys ))]. Interface ().( string ))
72
+ ki := rand .Intn (len (kv ))
69
73
70
- kv [string (key )] = ""
71
- _ , err := smt .Update (key , defaultValue )
72
- if err != nil {
73
- t .Errorf ("error: %v" , err )
74
+ err := smt .Delete (kv [ki ].key )
75
+ if err != nil && err != ErrKeyNotPresent {
76
+ t .Fatalf ("error: %v" , err )
74
77
}
78
+ kv [ki ].val = defaultValue
75
79
}
76
-
77
- bulkCheckAll (t , smt , & kv )
78
80
}
81
+ bulkCheckAll (t , smt , kv )
79
82
}
80
83
81
- func bulkCheckAll (t * testing.T , smt * SparseMerkleTree , kv * map [string ]string ) {
82
- for k , v := range * kv {
83
- value , err := smt .Get ([]byte (k ))
84
+ func bulkCheckAll (t * testing.T , smt * SMTWithStorage , kv []bulkop ) {
85
+ for ki := range kv {
86
+ k , v := kv [ki ].key , kv [ki ].val
87
+
88
+ value , err := smt .GetValue ([]byte (k ))
84
89
if err != nil {
85
90
t .Errorf ("error: %v" , err )
86
91
}
87
92
if ! bytes .Equal ([]byte (v ), value ) {
88
- t .Error ( "got incorrect value when bulk testing operations" )
93
+ t .Errorf ( "Incorrect value (i=%d)" , ki )
89
94
}
90
95
91
96
// Generate and verify a Merkle proof for this key.
92
97
proof , err := smt .Prove ([]byte (k ))
93
98
if err != nil {
94
99
t .Errorf ("error: %v" , err )
95
100
}
96
- if ! VerifyProof (proof , smt .Root (), []byte (k ), []byte (v ), smt .th . hasher ) {
97
- t .Error ("Merkle proof failed to verify" )
101
+ if ! VerifyProof (proof , smt .Root (), []byte (k ), []byte (v ), smt .Spec () ) {
102
+ t .Fatalf ("Merkle proof failed to verify (i=%d): %v" , ki , [] byte ( k ) )
98
103
}
99
- compactProof , err := smt . ProveCompact ([]byte (k ))
104
+ compactProof , err := ProveCompact ([]byte (k ), smt )
100
105
if err != nil {
101
106
t .Errorf ("error: %v" , err )
102
107
}
103
- if ! VerifyCompactProof (compactProof , smt .Root (), []byte (k ), []byte (v ), smt .th . hasher ) {
104
- t .Error ( " Merkle proof failed to verify" )
108
+ if ! VerifyCompactProof (compactProof , smt .Root (), []byte (k ), []byte (v ), smt .Spec () ) {
109
+ t .Fatalf ( "Compact Merkle proof failed to verify (i=%d): %v" , ki , [] byte ( k ) )
105
110
}
106
111
107
- if v == "" {
112
+ if v == nil {
108
113
continue
109
114
}
110
115
111
116
// Check that the key is at the correct height in the tree.
112
117
largestCommonPrefix := 0
113
- for k2 , v2 := range * kv {
114
- if v2 == "" {
118
+ for ki2 := range kv {
119
+ k2 , v2 := kv [ki2 ].key , kv [ki2 ].val
120
+ if v2 == nil {
115
121
continue
116
122
}
117
- commonPrefix := countCommonPrefix (smt .th .path ([]byte (k )), smt .th .path ([]byte (k2 )))
118
- if commonPrefix != smt .depth () && commonPrefix > largestCommonPrefix {
123
+
124
+ ph := smt .Spec ().ph
125
+ commonPrefix := countCommonPrefix (ph .Path ([]byte (k )), ph .Path ([]byte (k2 )), 0 )
126
+ if commonPrefix != smt .Spec ().depth () && commonPrefix > largestCommonPrefix {
119
127
largestCommonPrefix = commonPrefix
120
128
}
121
129
}
122
- sideNodes , _ , _ , _ , err := smt .sideNodesForRoot (smt .th .path ([]byte (k )), smt .Root (), false )
123
- if err != nil {
124
- t .Errorf ("error: %v" , err )
125
- }
126
- numSideNodes := 0
127
- for _ , v := range sideNodes {
128
- if v != nil {
129
- numSideNodes ++
130
- }
131
- }
132
- if numSideNodes != largestCommonPrefix + 1 && (numSideNodes != 0 && largestCommonPrefix != 0 ) {
133
- t .Error ("leaf is at unexpected height" )
130
+ if len (proof .SideNodes ) != largestCommonPrefix + 1 &&
131
+ (len (proof .SideNodes ) != 0 && largestCommonPrefix != 0 ) {
132
+ t .Errorf ("leaf is at unexpected height (ki=%d)" , ki )
134
133
}
135
134
}
136
135
}
0 commit comments