github.com/ethereum/go-ethereum@v1.14.4-0.20240516095835-473ee8fc07a3/core/block_validator_test.go (about) 1 // Copyright 2015 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 "math/big" 21 "testing" 22 "time" 23 24 "github.com/ethereum/go-ethereum/common" 25 "github.com/ethereum/go-ethereum/consensus" 26 "github.com/ethereum/go-ethereum/consensus/beacon" 27 "github.com/ethereum/go-ethereum/consensus/clique" 28 "github.com/ethereum/go-ethereum/consensus/ethash" 29 "github.com/ethereum/go-ethereum/core/rawdb" 30 "github.com/ethereum/go-ethereum/core/types" 31 "github.com/ethereum/go-ethereum/core/vm" 32 "github.com/ethereum/go-ethereum/crypto" 33 "github.com/ethereum/go-ethereum/params" 34 ) 35 36 // Tests that simple header verification works, for both good and bad blocks. 37 func TestHeaderVerification(t *testing.T) { 38 testHeaderVerification(t, rawdb.HashScheme) 39 testHeaderVerification(t, rawdb.PathScheme) 40 } 41 42 func testHeaderVerification(t *testing.T, scheme string) { 43 // Create a simple chain to verify 44 var ( 45 gspec = &Genesis{Config: params.TestChainConfig} 46 _, blocks, _ = GenerateChainWithGenesis(gspec, ethash.NewFaker(), 8, nil) 47 ) 48 headers := make([]*types.Header, len(blocks)) 49 for i, block := range blocks { 50 headers[i] = block.Header() 51 } 52 // Run the header checker for blocks one-by-one, checking for both valid and invalid nonces 53 chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) 54 defer chain.Stop() 55 56 for i := 0; i < len(blocks); i++ { 57 for j, valid := range []bool{true, false} { 58 var results <-chan error 59 60 if valid { 61 engine := ethash.NewFaker() 62 _, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}) 63 } else { 64 engine := ethash.NewFakeFailer(headers[i].Number.Uint64()) 65 _, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}) 66 } 67 // Wait for the verification result 68 select { 69 case result := <-results: 70 if (result == nil) != valid { 71 t.Errorf("test %d.%d: validity mismatch: have %v, want %v", i, j, result, valid) 72 } 73 case <-time.After(time.Second): 74 t.Fatalf("test %d.%d: verification timeout", i, j) 75 } 76 // Make sure no more data is returned 77 select { 78 case result := <-results: 79 t.Fatalf("test %d.%d: unexpected result returned: %v", i, j, result) 80 case <-time.After(25 * time.Millisecond): 81 } 82 } 83 chain.InsertChain(blocks[i : i+1]) 84 } 85 } 86 87 func TestHeaderVerificationForMergingClique(t *testing.T) { testHeaderVerificationForMerging(t, true) } 88 func TestHeaderVerificationForMergingEthash(t *testing.T) { testHeaderVerificationForMerging(t, false) } 89 90 // Tests the verification for eth1/2 merging, including pre-merge and post-merge 91 func testHeaderVerificationForMerging(t *testing.T, isClique bool) { 92 var ( 93 gspec *Genesis 94 preBlocks []*types.Block 95 postBlocks []*types.Block 96 engine consensus.Engine 97 ) 98 if isClique { 99 var ( 100 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 101 addr = crypto.PubkeyToAddress(key.PublicKey) 102 config = *params.AllCliqueProtocolChanges 103 ) 104 engine = beacon.New(clique.New(params.AllCliqueProtocolChanges.Clique, rawdb.NewMemoryDatabase())) 105 gspec = &Genesis{ 106 Config: &config, 107 ExtraData: make([]byte, 32+common.AddressLength+crypto.SignatureLength), 108 Alloc: map[common.Address]types.Account{ 109 addr: {Balance: big.NewInt(1)}, 110 }, 111 BaseFee: big.NewInt(params.InitialBaseFee), 112 Difficulty: new(big.Int), 113 } 114 copy(gspec.ExtraData[32:], addr[:]) 115 116 td := 0 117 genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil) 118 for i, block := range blocks { 119 header := block.Header() 120 if i > 0 { 121 header.ParentHash = blocks[i-1].Hash() 122 } 123 header.Extra = make([]byte, 32+crypto.SignatureLength) 124 header.Difficulty = big.NewInt(2) 125 126 sig, _ := crypto.Sign(engine.SealHash(header).Bytes(), key) 127 copy(header.Extra[len(header.Extra)-crypto.SignatureLength:], sig) 128 blocks[i] = block.WithSeal(header) 129 130 // calculate td 131 td += int(block.Difficulty().Uint64()) 132 } 133 preBlocks = blocks 134 gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td)) 135 postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, nil) 136 } else { 137 config := *params.TestChainConfig 138 gspec = &Genesis{Config: &config} 139 engine = beacon.New(ethash.NewFaker()) 140 td := int(params.GenesisDifficulty.Uint64()) 141 genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil) 142 for _, block := range blocks { 143 // calculate td 144 td += int(block.Difficulty().Uint64()) 145 } 146 preBlocks = blocks 147 gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td)) 148 t.Logf("Set ttd to %v\n", gspec.Config.TerminalTotalDifficulty) 149 postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, func(i int, gen *BlockGen) { 150 gen.SetPoS() 151 }) 152 } 153 // Assemble header batch 154 preHeaders := make([]*types.Header, len(preBlocks)) 155 for i, block := range preBlocks { 156 preHeaders[i] = block.Header() 157 } 158 postHeaders := make([]*types.Header, len(postBlocks)) 159 for i, block := range postBlocks { 160 postHeaders[i] = block.Header() 161 } 162 // Run the header checker for blocks one-by-one, checking for both valid and invalid nonces 163 chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil) 164 defer chain.Stop() 165 166 // Verify the blocks before the merging 167 for i := 0; i < len(preBlocks); i++ { 168 _, results := engine.VerifyHeaders(chain, []*types.Header{preHeaders[i]}) 169 // Wait for the verification result 170 select { 171 case result := <-results: 172 if result != nil { 173 t.Errorf("pre-block %d: verification failed %v", i, result) 174 } 175 case <-time.After(time.Second): 176 t.Fatalf("pre-block %d: verification timeout", i) 177 } 178 // Make sure no more data is returned 179 select { 180 case result := <-results: 181 t.Fatalf("pre-block %d: unexpected result returned: %v", i, result) 182 case <-time.After(25 * time.Millisecond): 183 } 184 chain.InsertChain(preBlocks[i : i+1]) 185 } 186 // Verify the blocks after the merging 187 for i := 0; i < len(postBlocks); i++ { 188 _, results := engine.VerifyHeaders(chain, []*types.Header{postHeaders[i]}) 189 // Wait for the verification result 190 select { 191 case result := <-results: 192 if result != nil { 193 t.Errorf("post-block %d: verification failed %v", i, result) 194 } 195 case <-time.After(time.Second): 196 t.Fatalf("test %d: verification timeout", i) 197 } 198 // Make sure no more data is returned 199 select { 200 case result := <-results: 201 t.Fatalf("post-block %d: unexpected result returned: %v", i, result) 202 case <-time.After(25 * time.Millisecond): 203 } 204 chain.InsertBlockWithoutSetHead(postBlocks[i]) 205 } 206 207 // Verify the blocks with pre-merge blocks and post-merge blocks 208 var headers []*types.Header 209 for _, block := range preBlocks { 210 headers = append(headers, block.Header()) 211 } 212 for _, block := range postBlocks { 213 headers = append(headers, block.Header()) 214 } 215 _, results := engine.VerifyHeaders(chain, headers) 216 for i := 0; i < len(headers); i++ { 217 select { 218 case result := <-results: 219 if result != nil { 220 t.Errorf("test %d: verification failed %v", i, result) 221 } 222 case <-time.After(time.Second): 223 t.Fatalf("test %d: verification timeout", i) 224 } 225 } 226 // Make sure no more data is returned 227 select { 228 case result := <-results: 229 t.Fatalf("unexpected result returned: %v", result) 230 case <-time.After(25 * time.Millisecond): 231 } 232 } 233 234 func TestCalcGasLimit(t *testing.T) { 235 for i, tc := range []struct { 236 pGasLimit uint64 237 max uint64 238 min uint64 239 }{ 240 {20000000, 20019530, 19980470}, 241 {40000000, 40039061, 39960939}, 242 } { 243 // Increase 244 if have, want := CalcGasLimit(tc.pGasLimit, 2*tc.pGasLimit), tc.max; have != want { 245 t.Errorf("test %d: have %d want <%d", i, have, want) 246 } 247 // Decrease 248 if have, want := CalcGasLimit(tc.pGasLimit, 0), tc.min; have != want { 249 t.Errorf("test %d: have %d want >%d", i, have, want) 250 } 251 // Small decrease 252 if have, want := CalcGasLimit(tc.pGasLimit, tc.pGasLimit-1), tc.pGasLimit-1; have != want { 253 t.Errorf("test %d: have %d want %d", i, have, want) 254 } 255 // Small increase 256 if have, want := CalcGasLimit(tc.pGasLimit, tc.pGasLimit+1), tc.pGasLimit+1; have != want { 257 t.Errorf("test %d: have %d want %d", i, have, want) 258 } 259 // No change 260 if have, want := CalcGasLimit(tc.pGasLimit, tc.pGasLimit), tc.pGasLimit; have != want { 261 t.Errorf("test %d: have %d want %d", i, have, want) 262 } 263 } 264 }