github.com/theQRL/go-zond@v0.1.1/core/rlp_test.go (about) 1 // Copyright 2020 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 core 18 19 import ( 20 "fmt" 21 "math/big" 22 "testing" 23 24 "github.com/theQRL/go-zond/common" 25 "github.com/theQRL/go-zond/consensus/ethash" 26 "github.com/theQRL/go-zond/core/types" 27 "github.com/theQRL/go-zond/crypto" 28 "github.com/theQRL/go-zond/params" 29 "github.com/theQRL/go-zond/pqcrypto" 30 "github.com/theQRL/go-zond/rlp" 31 "golang.org/x/crypto/sha3" 32 ) 33 34 func getBlock(transactions int, uncles int, dataSize int) *types.Block { 35 var ( 36 aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") 37 engine = ethash.NewFaker() 38 39 // A sender who makes transactions, has some funds 40 d, _ = pqcrypto.HexToDilithium("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 41 address = d.GetAddress() 42 funds = big.NewInt(1_000_000_000_000_000_000) 43 gspec = &Genesis{ 44 Config: params.TestChainConfig, 45 Alloc: GenesisAlloc{address: {Balance: funds}}, 46 } 47 ) 48 // We need to generate as many blocks +1 as uncles 49 _, blocks, _ := GenerateChainWithGenesis(gspec, engine, uncles+1, 50 func(n int, b *BlockGen) { 51 if n == uncles { 52 // Add transactions and stuff on the last block 53 for i := 0; i < transactions; i++ { 54 tx, _ := types.SignTx(types.NewTransaction(uint64(i), aa, 55 big.NewInt(0), 50000, b.header.BaseFee, make([]byte, dataSize)), types.HomesteadSigner{}, d) 56 b.AddTx(tx) 57 } 58 for i := 0; i < uncles; i++ { 59 b.AddUncle(&types.Header{ParentHash: b.PrevBlock(n - 1 - i).Hash(), Number: big.NewInt(int64(n - i))}) 60 } 61 } 62 }) 63 block := blocks[len(blocks)-1] 64 return block 65 } 66 67 // TestRlpIterator tests that individual transactions can be picked out 68 // from blocks without full unmarshalling/marshalling 69 func TestRlpIterator(t *testing.T) { 70 for _, tt := range []struct { 71 txs int 72 uncles int 73 datasize int 74 }{ 75 {0, 0, 0}, 76 {0, 2, 0}, 77 {10, 0, 0}, 78 {10, 2, 0}, 79 {10, 2, 50}, 80 } { 81 testRlpIterator(t, tt.txs, tt.uncles, tt.datasize) 82 } 83 } 84 85 func testRlpIterator(t *testing.T, txs, uncles, datasize int) { 86 desc := fmt.Sprintf("%d txs [%d datasize] and %d uncles", txs, datasize, uncles) 87 bodyRlp, _ := rlp.EncodeToBytes(getBlock(txs, uncles, datasize).Body()) 88 it, err := rlp.NewListIterator(bodyRlp) 89 if err != nil { 90 t.Fatal(err) 91 } 92 // Check that txs exist 93 if !it.Next() { 94 t.Fatal("expected two elems, got zero") 95 } 96 txdata := it.Value() 97 // Check that uncles exist 98 if !it.Next() { 99 t.Fatal("expected two elems, got one") 100 } 101 // No more after that 102 if it.Next() { 103 t.Fatal("expected only two elems, got more") 104 } 105 txIt, err := rlp.NewListIterator(txdata) 106 if err != nil { 107 t.Fatal(err) 108 } 109 var gotHashes []common.Hash 110 var expHashes []common.Hash 111 for txIt.Next() { 112 gotHashes = append(gotHashes, crypto.Keccak256Hash(txIt.Value())) 113 } 114 115 var expBody types.Body 116 err = rlp.DecodeBytes(bodyRlp, &expBody) 117 if err != nil { 118 t.Fatal(err) 119 } 120 for _, tx := range expBody.Transactions { 121 expHashes = append(expHashes, tx.Hash()) 122 } 123 if gotLen, expLen := len(gotHashes), len(expHashes); gotLen != expLen { 124 t.Fatalf("testcase %v: length wrong, got %d exp %d", desc, gotLen, expLen) 125 } 126 // also sanity check against input 127 if gotLen := len(gotHashes); gotLen != txs { 128 t.Fatalf("testcase %v: length wrong, got %d exp %d", desc, gotLen, txs) 129 } 130 for i, got := range gotHashes { 131 if exp := expHashes[i]; got != exp { 132 t.Errorf("testcase %v: hash wrong, got %x, exp %x", desc, got, exp) 133 } 134 } 135 } 136 137 // BenchmarkHashing compares the speeds of hashing a rlp raw data directly 138 // without the unmarshalling/marshalling step 139 func BenchmarkHashing(b *testing.B) { 140 // Make a pretty fat block 141 var ( 142 bodyRlp []byte 143 blockRlp []byte 144 ) 145 { 146 block := getBlock(200, 2, 50) 147 bodyRlp, _ = rlp.EncodeToBytes(block.Body()) 148 blockRlp, _ = rlp.EncodeToBytes(block) 149 } 150 var got common.Hash 151 var hasher = sha3.NewLegacyKeccak256() 152 b.Run("iteratorhashing", func(b *testing.B) { 153 b.ResetTimer() 154 for i := 0; i < b.N; i++ { 155 var hash common.Hash 156 it, err := rlp.NewListIterator(bodyRlp) 157 if err != nil { 158 b.Fatal(err) 159 } 160 it.Next() 161 txs := it.Value() 162 txIt, err := rlp.NewListIterator(txs) 163 if err != nil { 164 b.Fatal(err) 165 } 166 for txIt.Next() { 167 hasher.Reset() 168 hasher.Write(txIt.Value()) 169 hasher.Sum(hash[:0]) 170 got = hash 171 } 172 } 173 }) 174 var exp common.Hash 175 b.Run("fullbodyhashing", func(b *testing.B) { 176 b.ResetTimer() 177 for i := 0; i < b.N; i++ { 178 var body types.Body 179 rlp.DecodeBytes(bodyRlp, &body) 180 for _, tx := range body.Transactions { 181 exp = tx.Hash() 182 } 183 } 184 }) 185 b.Run("fullblockhashing", func(b *testing.B) { 186 b.ResetTimer() 187 for i := 0; i < b.N; i++ { 188 var block types.Block 189 rlp.DecodeBytes(blockRlp, &block) 190 for _, tx := range block.Transactions() { 191 tx.Hash() 192 } 193 } 194 }) 195 if got != exp { 196 b.Fatalf("hash wrong, got %x exp %x", got, exp) 197 } 198 }