|
1 | 1 | package trie
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "bytes" |
| 5 | + "math/big" |
4 | 6 | "testing"
|
5 | 7 |
|
6 | 8 | "github.com/XinFinOrg/XDPoSChain/common"
|
| 9 | + "github.com/XinFinOrg/XDPoSChain/crypto" |
7 | 10 | "github.com/XinFinOrg/XDPoSChain/ethdb/memorydb"
|
8 | 11 | )
|
9 | 12 |
|
@@ -119,3 +122,51 @@ func TestUpdateVariableKeys(t *testing.T) {
|
119 | 122 | t.Fatalf("error %x != %x", st.Hash(), nt.Hash())
|
120 | 123 | }
|
121 | 124 | }
|
| 125 | + |
| 126 | +// TestStacktrieNotModifyValues checks that inserting blobs of data into the |
| 127 | +// stacktrie does not mutate the blobs |
| 128 | +func TestStacktrieNotModifyValues(t *testing.T) { |
| 129 | + st := NewStackTrie(nil) |
| 130 | + { // Test a very small trie |
| 131 | + // Give it the value as a slice with large backing alloc, |
| 132 | + // so if the stacktrie tries to append, it won't have to realloc |
| 133 | + value := make([]byte, 1, 100) |
| 134 | + value[0] = 0x2 |
| 135 | + want := common.CopyBytes(value) |
| 136 | + st.TryUpdate([]byte{0x01}, value) |
| 137 | + st.Hash() |
| 138 | + if have := value; !bytes.Equal(have, want) { |
| 139 | + t.Fatalf("tiny trie: have %#x want %#x", have, want) |
| 140 | + } |
| 141 | + st = NewStackTrie(nil) |
| 142 | + } |
| 143 | + // Test with a larger trie |
| 144 | + keyB := big.NewInt(1) |
| 145 | + keyDelta := big.NewInt(1) |
| 146 | + var vals [][]byte |
| 147 | + getValue := func(i int) []byte { |
| 148 | + if i%2 == 0 { // large |
| 149 | + return crypto.Keccak256(big.NewInt(int64(i)).Bytes()) |
| 150 | + } else { //small |
| 151 | + return big.NewInt(int64(i)).Bytes() |
| 152 | + } |
| 153 | + } |
| 154 | + |
| 155 | + for i := 0; i < 1000; i++ { |
| 156 | + key := common.BigToHash(keyB) |
| 157 | + value := getValue(i) |
| 158 | + st.TryUpdate(key.Bytes(), value) |
| 159 | + vals = append(vals, value) |
| 160 | + keyB = keyB.Add(keyB, keyDelta) |
| 161 | + keyDelta.Add(keyDelta, common.Big1) |
| 162 | + } |
| 163 | + st.Hash() |
| 164 | + for i := 0; i < 1000; i++ { |
| 165 | + want := getValue(i) |
| 166 | + |
| 167 | + have := vals[i] |
| 168 | + if !bytes.Equal(have, want) { |
| 169 | + t.Fatalf("item %d, have %#x want %#x", i, have, want) |
| 170 | + } |
| 171 | + } |
| 172 | +} |
0 commit comments