github.com/haliliceylan/bsc@v1.1.10-0.20220501224556-eb78d644ebcb/core/types/hashing_test.go (about)

     1  // Copyright 2021 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package types_test
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"io"
    23  	"math/big"
    24  	mrand "math/rand"
    25  	"testing"
    26  
    27  	"github.com/ethereum/go-ethereum/common"
    28  	"github.com/ethereum/go-ethereum/common/hexutil"
    29  	"github.com/ethereum/go-ethereum/core/types"
    30  	"github.com/ethereum/go-ethereum/crypto"
    31  	"github.com/ethereum/go-ethereum/rlp"
    32  	"github.com/ethereum/go-ethereum/trie"
    33  )
    34  
    35  func TestDeriveSha(t *testing.T) {
    36  	txs, err := genTxs(0)
    37  	if err != nil {
    38  		t.Fatal(err)
    39  	}
    40  	for len(txs) < 1000 {
    41  		exp := types.DeriveSha(txs, new(trie.Trie))
    42  		got := types.DeriveSha(txs, trie.NewStackTrie(nil))
    43  		if !bytes.Equal(got[:], exp[:]) {
    44  			t.Fatalf("%d txs: got %x exp %x", len(txs), got, exp)
    45  		}
    46  		newTxs, err := genTxs(uint64(len(txs) + 1))
    47  		if err != nil {
    48  			t.Fatal(err)
    49  		}
    50  		txs = append(txs, newTxs...)
    51  	}
    52  }
    53  
    54  // TestEIP2718DeriveSha tests that the input to the DeriveSha function is correct.
    55  func TestEIP2718DeriveSha(t *testing.T) {
    56  	for _, tc := range []struct {
    57  		rlpData string
    58  		exp     string
    59  	}{
    60  		{
    61  			rlpData: "0xb8a701f8a486796f6c6f763380843b9aca008262d4948a8eafb1cf62bfbeb1741769dae1a9dd479961928080f838f7940000000000000000000000000000000000001337e1a0000000000000000000000000000000000000000000000000000000000000000080a0775101f92dcca278a56bfe4d613428624a1ebfc3cd9e0bcc1de80c41455b9021a06c9deac205afe7b124907d4ba54a9f46161498bd3990b90d175aac12c9a40ee9",
    62  			exp:     "01 01f8a486796f6c6f763380843b9aca008262d4948a8eafb1cf62bfbeb1741769dae1a9dd479961928080f838f7940000000000000000000000000000000000001337e1a0000000000000000000000000000000000000000000000000000000000000000080a0775101f92dcca278a56bfe4d613428624a1ebfc3cd9e0bcc1de80c41455b9021a06c9deac205afe7b124907d4ba54a9f46161498bd3990b90d175aac12c9a40ee9\n80 01f8a486796f6c6f763380843b9aca008262d4948a8eafb1cf62bfbeb1741769dae1a9dd479961928080f838f7940000000000000000000000000000000000001337e1a0000000000000000000000000000000000000000000000000000000000000000080a0775101f92dcca278a56bfe4d613428624a1ebfc3cd9e0bcc1de80c41455b9021a06c9deac205afe7b124907d4ba54a9f46161498bd3990b90d175aac12c9a40ee9\n",
    63  		},
    64  	} {
    65  		d := &hashToHumanReadable{}
    66  		var t1, t2 types.Transaction
    67  		rlp.DecodeBytes(common.FromHex(tc.rlpData), &t1)
    68  		rlp.DecodeBytes(common.FromHex(tc.rlpData), &t2)
    69  		txs := types.Transactions{&t1, &t2}
    70  		types.DeriveSha(txs, d)
    71  		if tc.exp != string(d.data) {
    72  			t.Fatalf("Want\n%v\nhave:\n%v", tc.exp, string(d.data))
    73  		}
    74  	}
    75  }
    76  
    77  func BenchmarkDeriveSha200(b *testing.B) {
    78  	txs, err := genTxs(200)
    79  	if err != nil {
    80  		b.Fatal(err)
    81  	}
    82  	var exp common.Hash
    83  	var got common.Hash
    84  	b.Run("std_trie", func(b *testing.B) {
    85  		b.ResetTimer()
    86  		b.ReportAllocs()
    87  		for i := 0; i < b.N; i++ {
    88  			exp = types.DeriveSha(txs, new(trie.Trie))
    89  		}
    90  	})
    91  
    92  	b.Run("stack_trie", func(b *testing.B) {
    93  		b.ResetTimer()
    94  		b.ReportAllocs()
    95  		for i := 0; i < b.N; i++ {
    96  			got = types.DeriveSha(txs, trie.NewStackTrie(nil))
    97  		}
    98  	})
    99  	if got != exp {
   100  		b.Errorf("got %x exp %x", got, exp)
   101  	}
   102  }
   103  
   104  func TestFuzzDeriveSha(t *testing.T) {
   105  	// increase this for longer runs -- it's set to quite low for travis
   106  	rndSeed := mrand.Int()
   107  	for i := 0; i < 10; i++ {
   108  		seed := rndSeed + i
   109  		exp := types.DeriveSha(newDummy(i), new(trie.Trie))
   110  		got := types.DeriveSha(newDummy(i), trie.NewStackTrie(nil))
   111  		if !bytes.Equal(got[:], exp[:]) {
   112  			printList(newDummy(seed))
   113  			t.Fatalf("seed %d: got %x exp %x", seed, got, exp)
   114  		}
   115  	}
   116  }
   117  
   118  // TestDerivableList contains testcases found via fuzzing
   119  func TestDerivableList(t *testing.T) {
   120  	type tcase []string
   121  	tcs := []tcase{
   122  		{
   123  			"0xc041",
   124  		},
   125  		{
   126  			"0xf04cf757812428b0763112efb33b6f4fad7deb445e",
   127  			"0xf04cf757812428b0763112efb33b6f4fad7deb445e",
   128  		},
   129  		{
   130  			"0xca410605310cdc3bb8d4977ae4f0143df54a724ed873457e2272f39d66e0460e971d9d",
   131  			"0x6cd850eca0a7ac46bb1748d7b9cb88aa3bd21c57d852c28198ad8fa422c4595032e88a4494b4778b36b944fe47a52b8c5cd312910139dfcb4147ab8e972cc456bcb063f25dd78f54c4d34679e03142c42c662af52947d45bdb6e555751334ace76a5080ab5a0256a1d259855dfc5c0b8023b25befbb13fd3684f9f755cbd3d63544c78ee2001452dd54633a7593ade0b183891a0a4e9c7844e1254005fbe592b1b89149a502c24b6e1dca44c158aebedf01beae9c30cabe16a",
   132  			"0x14abd5c47c0be87b0454596baad2",
   133  			"0xca410605310cdc3bb8d4977ae4f0143df54a724ed873457e2272f39d66e0460e971d9d",
   134  		},
   135  	}
   136  	for i, tc := range tcs[1:] {
   137  		exp := types.DeriveSha(flatList(tc), new(trie.Trie))
   138  		got := types.DeriveSha(flatList(tc), trie.NewStackTrie(nil))
   139  		if !bytes.Equal(got[:], exp[:]) {
   140  			t.Fatalf("case %d: got %x exp %x", i, got, exp)
   141  		}
   142  	}
   143  }
   144  
   145  func genTxs(num uint64) (types.Transactions, error) {
   146  	key, err := crypto.HexToECDSA("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef")
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	var addr = crypto.PubkeyToAddress(key.PublicKey)
   151  	newTx := func(i uint64) (*types.Transaction, error) {
   152  		signer := types.NewEIP155Signer(big.NewInt(18))
   153  		utx := types.NewTransaction(i, addr, new(big.Int), 0, new(big.Int).SetUint64(10000000), nil)
   154  		tx, err := types.SignTx(utx, signer, key)
   155  		return tx, err
   156  	}
   157  	var txs types.Transactions
   158  	for i := uint64(0); i < num; i++ {
   159  		tx, err := newTx(i)
   160  		if err != nil {
   161  			return nil, err
   162  		}
   163  		txs = append(txs, tx)
   164  	}
   165  	return txs, nil
   166  }
   167  
   168  type dummyDerivableList struct {
   169  	len  int
   170  	seed int
   171  }
   172  
   173  func newDummy(seed int) *dummyDerivableList {
   174  	d := &dummyDerivableList{}
   175  	src := mrand.NewSource(int64(seed))
   176  	// don't use lists longer than 4K items
   177  	d.len = int(src.Int63() & 0x0FFF)
   178  	d.seed = seed
   179  	return d
   180  }
   181  
   182  func (d *dummyDerivableList) Len() int {
   183  	return d.len
   184  }
   185  
   186  func (d *dummyDerivableList) EncodeIndex(i int, w *bytes.Buffer) {
   187  	src := mrand.NewSource(int64(d.seed + i))
   188  	// max item size 256, at least 1 byte per item
   189  	size := 1 + src.Int63()&0x00FF
   190  	io.CopyN(w, mrand.New(src), size)
   191  }
   192  
   193  func printList(l types.DerivableList) {
   194  	fmt.Printf("list length: %d\n", l.Len())
   195  	fmt.Printf("{\n")
   196  	for i := 0; i < l.Len(); i++ {
   197  		var buf bytes.Buffer
   198  		l.EncodeIndex(i, &buf)
   199  		fmt.Printf("\"0x%x\",\n", buf.Bytes())
   200  	}
   201  	fmt.Printf("},\n")
   202  }
   203  
   204  type flatList []string
   205  
   206  func (f flatList) Len() int {
   207  	return len(f)
   208  }
   209  func (f flatList) EncodeIndex(i int, w *bytes.Buffer) {
   210  	w.Write(hexutil.MustDecode(f[i]))
   211  }
   212  
   213  type hashToHumanReadable struct {
   214  	data []byte
   215  }
   216  
   217  func (d *hashToHumanReadable) Reset() {
   218  	d.data = make([]byte, 0)
   219  }
   220  
   221  func (d *hashToHumanReadable) Update(i []byte, i2 []byte) {
   222  	l := fmt.Sprintf("%x %x\n", i, i2)
   223  	d.data = append(d.data, []byte(l)...)
   224  }
   225  
   226  func (d *hashToHumanReadable) Hash() common.Hash {
   227  	return common.Hash{}
   228  }