stacktrie_test.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. package trie
  2. import (
  3. "bytes"
  4. "fmt"
  5. "math/big"
  6. mrand "math/rand"
  7. "testing"
  8. "github.com/ethereum/go-ethereum/common"
  9. "github.com/ethereum/go-ethereum/common/hexutil"
  10. "github.com/ethereum/go-ethereum/core/types"
  11. "github.com/ethereum/go-ethereum/crypto"
  12. "github.com/ethereum/go-ethereum/ethdb/memorydb"
  13. )
  14. func TestSizeBug(t *testing.T) {
  15. st := NewStackTrie(nil)
  16. nt, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
  17. leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
  18. value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
  19. nt.TryUpdate(leaf, value)
  20. st.TryUpdate(leaf, value)
  21. if nt.Hash() != st.Hash() {
  22. t.Fatalf("error %x != %x", st.Hash(), nt.Hash())
  23. }
  24. }
  25. func TestEmptyBug(t *testing.T) {
  26. st := NewStackTrie(nil)
  27. nt, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
  28. //leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
  29. //value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
  30. kvs := []struct {
  31. K string
  32. V string
  33. }{
  34. {K: "405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace", V: "9496f4ec2bf9dab484cac6be589e8417d84781be08"},
  35. {K: "40edb63a35fcf86c08022722aa3287cdd36440d671b4918131b2514795fefa9c", V: "01"},
  36. {K: "b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6", V: "947a30f7736e48d6599356464ba4c150d8da0302ff"},
  37. {K: "c2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", V: "02"},
  38. }
  39. for _, kv := range kvs {
  40. nt.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
  41. st.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
  42. }
  43. if nt.Hash() != st.Hash() {
  44. t.Fatalf("error %x != %x", st.Hash(), nt.Hash())
  45. }
  46. }
  47. func TestValLength56(t *testing.T) {
  48. st := NewStackTrie(nil)
  49. nt, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
  50. //leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
  51. //value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
  52. kvs := []struct {
  53. K string
  54. V string
  55. }{
  56. {K: "405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace", V: "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"},
  57. }
  58. for _, kv := range kvs {
  59. nt.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
  60. st.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
  61. }
  62. if nt.Hash() != st.Hash() {
  63. t.Fatalf("error %x != %x", st.Hash(), nt.Hash())
  64. }
  65. }
  66. func genTxs(num uint64) (types.Transactions, error) {
  67. key, err := crypto.HexToECDSA("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef")
  68. if err != nil {
  69. return nil, err
  70. }
  71. var addr = crypto.PubkeyToAddress(key.PublicKey)
  72. newTx := func(i uint64) (*types.Transaction, error) {
  73. signer := types.NewEIP155Signer(big.NewInt(18))
  74. tx, err := types.SignTx(types.NewTransaction(i, addr, new(big.Int), 0, new(big.Int).SetUint64(10000000), nil), signer, key)
  75. return tx, err
  76. }
  77. var txs types.Transactions
  78. for i := uint64(0); i < num; i++ {
  79. tx, err := newTx(i)
  80. if err != nil {
  81. return nil, err
  82. }
  83. txs = append(txs, tx)
  84. }
  85. return txs, nil
  86. }
  87. func TestDeriveSha(t *testing.T) {
  88. txs, err := genTxs(0)
  89. if err != nil {
  90. t.Fatal(err)
  91. }
  92. for len(txs) < 1000 {
  93. exp := types.DeriveSha(txs, newEmpty())
  94. got := types.DeriveSha(txs, NewStackTrie(nil))
  95. if !bytes.Equal(got[:], exp[:]) {
  96. t.Fatalf("%d txs: got %x exp %x", len(txs), got, exp)
  97. }
  98. newTxs, err := genTxs(uint64(len(txs) + 1))
  99. if err != nil {
  100. t.Fatal(err)
  101. }
  102. txs = append(txs, newTxs...)
  103. }
  104. }
  105. func BenchmarkDeriveSha200(b *testing.B) {
  106. txs, err := genTxs(200)
  107. if err != nil {
  108. b.Fatal(err)
  109. }
  110. var exp common.Hash
  111. var got common.Hash
  112. b.Run("std_trie", func(b *testing.B) {
  113. b.ResetTimer()
  114. b.ReportAllocs()
  115. for i := 0; i < b.N; i++ {
  116. exp = types.DeriveSha(txs, newEmpty())
  117. }
  118. })
  119. b.Run("stack_trie", func(b *testing.B) {
  120. b.ResetTimer()
  121. b.ReportAllocs()
  122. for i := 0; i < b.N; i++ {
  123. got = types.DeriveSha(txs, NewStackTrie(nil))
  124. }
  125. })
  126. if got != exp {
  127. b.Errorf("got %x exp %x", got, exp)
  128. }
  129. }
  130. type dummyDerivableList struct {
  131. len int
  132. seed int
  133. }
  134. func newDummy(seed int) *dummyDerivableList {
  135. d := &dummyDerivableList{}
  136. src := mrand.NewSource(int64(seed))
  137. // don't use lists longer than 4K items
  138. d.len = int(src.Int63() & 0x0FFF)
  139. d.seed = seed
  140. return d
  141. }
  142. func (d *dummyDerivableList) Len() int {
  143. return d.len
  144. }
  145. func (d *dummyDerivableList) GetRlp(i int) []byte {
  146. src := mrand.NewSource(int64(d.seed + i))
  147. // max item size 256, at least 1 byte per item
  148. size := 1 + src.Int63()&0x00FF
  149. data := make([]byte, size)
  150. _, err := mrand.New(src).Read(data)
  151. if err != nil {
  152. panic(err)
  153. }
  154. return data
  155. }
  156. func printList(l types.DerivableList) {
  157. fmt.Printf("list length: %d\n", l.Len())
  158. fmt.Printf("{\n")
  159. for i := 0; i < l.Len(); i++ {
  160. v := l.GetRlp(i)
  161. fmt.Printf("\"0x%x\",\n", v)
  162. }
  163. fmt.Printf("},\n")
  164. }
  165. func TestFuzzDeriveSha(t *testing.T) {
  166. // increase this for longer runs -- it's set to quite low for travis
  167. rndSeed := mrand.Int()
  168. for i := 0; i < 10; i++ {
  169. seed := rndSeed + i
  170. exp := types.DeriveSha(newDummy(i), newEmpty())
  171. got := types.DeriveSha(newDummy(i), NewStackTrie(nil))
  172. if !bytes.Equal(got[:], exp[:]) {
  173. printList(newDummy(seed))
  174. t.Fatalf("seed %d: got %x exp %x", seed, got, exp)
  175. }
  176. }
  177. }
  178. type flatList struct {
  179. rlpvals []string
  180. }
  181. func newFlatList(rlpvals []string) *flatList {
  182. return &flatList{rlpvals}
  183. }
  184. func (f *flatList) Len() int {
  185. return len(f.rlpvals)
  186. }
  187. func (f *flatList) GetRlp(i int) []byte {
  188. return hexutil.MustDecode(f.rlpvals[i])
  189. }
  190. // TestDerivableList contains testcases found via fuzzing
  191. func TestDerivableList(t *testing.T) {
  192. type tcase []string
  193. tcs := []tcase{
  194. {
  195. "0xc041",
  196. },
  197. {
  198. "0xf04cf757812428b0763112efb33b6f4fad7deb445e",
  199. "0xf04cf757812428b0763112efb33b6f4fad7deb445e",
  200. },
  201. {
  202. "0xca410605310cdc3bb8d4977ae4f0143df54a724ed873457e2272f39d66e0460e971d9d",
  203. "0x6cd850eca0a7ac46bb1748d7b9cb88aa3bd21c57d852c28198ad8fa422c4595032e88a4494b4778b36b944fe47a52b8c5cd312910139dfcb4147ab8e972cc456bcb063f25dd78f54c4d34679e03142c42c662af52947d45bdb6e555751334ace76a5080ab5a0256a1d259855dfc5c0b8023b25befbb13fd3684f9f755cbd3d63544c78ee2001452dd54633a7593ade0b183891a0a4e9c7844e1254005fbe592b1b89149a502c24b6e1dca44c158aebedf01beae9c30cabe16a",
  204. "0x14abd5c47c0be87b0454596baad2",
  205. "0xca410605310cdc3bb8d4977ae4f0143df54a724ed873457e2272f39d66e0460e971d9d",
  206. },
  207. }
  208. for i, tc := range tcs[1:] {
  209. exp := types.DeriveSha(newFlatList(tc), newEmpty())
  210. got := types.DeriveSha(newFlatList(tc), NewStackTrie(nil))
  211. if !bytes.Equal(got[:], exp[:]) {
  212. t.Fatalf("case %d: got %x exp %x", i, got, exp)
  213. }
  214. }
  215. }