gitlab.com/flarenetwork/coreth@v0.1.1/core/blockchain_test.go (about) 1 // (c) 2020-2021, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package core 5 6 import ( 7 "math/big" 8 "testing" 9 10 "github.com/ethereum/go-ethereum/common" 11 "github.com/ethereum/go-ethereum/ethdb" 12 "gitlab.com/flarenetwork/coreth/consensus/dummy" 13 "gitlab.com/flarenetwork/coreth/core/rawdb" 14 "gitlab.com/flarenetwork/coreth/core/state" 15 "gitlab.com/flarenetwork/coreth/core/types" 16 "gitlab.com/flarenetwork/coreth/core/vm" 17 "gitlab.com/flarenetwork/coreth/params" 18 ) 19 20 func TestArchiveBlockChain(t *testing.T) { 21 create := func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error) { 22 // Import the chain. This runs all block validation rules. 23 blockchain, err := NewBlockChain( 24 db, 25 &CacheConfig{ 26 TrieCleanLimit: 256, 27 TrieDirtyLimit: 256, 28 Pruning: false, // Archive mode 29 SnapshotLimit: 256, 30 }, 31 chainConfig, 32 dummy.NewDummyEngine(&dummy.ConsensusCallbacks{ 33 OnExtraStateChange: func(block *types.Block, sdb *state.StateDB) error { 34 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(block.Number().Int64())) 35 return nil 36 }, 37 OnFinalizeAndAssemble: func(header *types.Header, sdb *state.StateDB, txs []*types.Transaction) ([]byte, error) { 38 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(header.Number.Int64())) 39 return nil, nil 40 }, 41 }), 42 vm.Config{}, 43 lastAcceptedHash, 44 ) 45 return blockchain, err 46 } 47 for _, tt := range tests { 48 t.Run(tt.Name, func(t *testing.T) { 49 tt.testFunc(t, create) 50 }) 51 } 52 } 53 54 func TestArchiveBlockChainSnapsDisabled(t *testing.T) { 55 create := func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error) { 56 // Import the chain. This runs all block validation rules. 57 blockchain, err := NewBlockChain( 58 db, 59 &CacheConfig{ 60 TrieCleanLimit: 256, 61 TrieDirtyLimit: 256, 62 Pruning: false, // Archive mode 63 SnapshotLimit: 0, // Disable snapshots 64 }, 65 chainConfig, 66 dummy.NewDummyEngine(&dummy.ConsensusCallbacks{ 67 OnExtraStateChange: func(block *types.Block, sdb *state.StateDB) error { 68 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(block.Number().Int64())) 69 return nil 70 }, 71 OnFinalizeAndAssemble: func(header *types.Header, sdb *state.StateDB, txs []*types.Transaction) ([]byte, error) { 72 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(header.Number.Int64())) 73 return nil, nil 74 }, 75 }), 76 vm.Config{}, 77 lastAcceptedHash, 78 ) 79 return blockchain, err 80 } 81 for _, tt := range tests { 82 t.Run(tt.Name, func(t *testing.T) { 83 tt.testFunc(t, create) 84 }) 85 } 86 } 87 88 func TestPruningBlockChain(t *testing.T) { 89 create := func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error) { 90 // Import the chain. This runs all block validation rules. 91 blockchain, err := NewBlockChain( 92 db, 93 &CacheConfig{ 94 TrieCleanLimit: 256, 95 TrieDirtyLimit: 256, 96 Pruning: true, // Enable pruning 97 SnapshotLimit: 256, 98 }, 99 chainConfig, 100 dummy.NewDummyEngine(&dummy.ConsensusCallbacks{ 101 OnExtraStateChange: func(block *types.Block, sdb *state.StateDB) error { 102 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(block.Number().Int64())) 103 return nil 104 }, 105 OnFinalizeAndAssemble: func(header *types.Header, sdb *state.StateDB, txs []*types.Transaction) ([]byte, error) { 106 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(header.Number.Int64())) 107 return nil, nil 108 }, 109 }), 110 vm.Config{}, 111 lastAcceptedHash, 112 ) 113 return blockchain, err 114 } 115 for _, tt := range tests { 116 t.Run(tt.Name, func(t *testing.T) { 117 tt.testFunc(t, create) 118 }) 119 } 120 } 121 122 func TestPruningBlockChainSnapsDisabled(t *testing.T) { 123 create := func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error) { 124 // Import the chain. This runs all block validation rules. 125 blockchain, err := NewBlockChain( 126 db, 127 &CacheConfig{ 128 TrieCleanLimit: 256, 129 TrieDirtyLimit: 256, 130 Pruning: true, // Enable pruning 131 SnapshotLimit: 0, // Disable snapshots 132 }, 133 chainConfig, 134 dummy.NewDummyEngine(&dummy.ConsensusCallbacks{ 135 OnExtraStateChange: func(block *types.Block, sdb *state.StateDB) error { 136 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(block.Number().Int64())) 137 return nil 138 }, 139 OnFinalizeAndAssemble: func(header *types.Header, sdb *state.StateDB, txs []*types.Transaction) ([]byte, error) { 140 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(header.Number.Int64())) 141 return nil, nil 142 }, 143 }), 144 vm.Config{}, 145 lastAcceptedHash, 146 ) 147 return blockchain, err 148 } 149 for _, tt := range tests { 150 t.Run(tt.Name, func(t *testing.T) { 151 tt.testFunc(t, create) 152 }) 153 } 154 } 155 156 type wrappedStateManager struct { 157 TrieWriter 158 } 159 160 func (w *wrappedStateManager) Shutdown() error { return nil } 161 162 func TestPruningBlockChainUngracefulShutdown(t *testing.T) { 163 create := func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error) { 164 // Import the chain. This runs all block validation rules. 165 blockchain, err := NewBlockChain( 166 db, 167 &CacheConfig{ 168 TrieCleanLimit: 256, 169 TrieDirtyLimit: 256, 170 Pruning: true, // Enable pruning 171 SnapshotLimit: 256, 172 }, 173 chainConfig, 174 dummy.NewDummyEngine(&dummy.ConsensusCallbacks{ 175 OnExtraStateChange: func(block *types.Block, sdb *state.StateDB) error { 176 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(block.Number().Int64())) 177 return nil 178 }, 179 OnFinalizeAndAssemble: func(header *types.Header, sdb *state.StateDB, txs []*types.Transaction) ([]byte, error) { 180 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(header.Number.Int64())) 181 return nil, nil 182 }, 183 }), 184 vm.Config{}, 185 lastAcceptedHash, 186 ) 187 if err != nil { 188 return nil, err 189 } 190 191 // Overwrite state manager, so that Shutdown is not called. 192 // This tests to ensure that the state manager handles an ungraceful shutdown correctly. 193 blockchain.stateManager = &wrappedStateManager{TrieWriter: blockchain.stateManager} 194 return blockchain, err 195 } 196 for _, tt := range tests { 197 t.Run(tt.Name, func(t *testing.T) { 198 tt.testFunc(t, create) 199 }) 200 } 201 } 202 203 func TestPruningBlockChainUngracefulShutdownSnapsDisabled(t *testing.T) { 204 create := func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error) { 205 // Import the chain. This runs all block validation rules. 206 blockchain, err := NewBlockChain( 207 db, 208 &CacheConfig{ 209 TrieCleanLimit: 256, 210 TrieDirtyLimit: 256, 211 Pruning: true, // Enable pruning 212 SnapshotLimit: 0, // Disable snapshots 213 }, 214 chainConfig, 215 dummy.NewDummyEngine(&dummy.ConsensusCallbacks{ 216 OnExtraStateChange: func(block *types.Block, sdb *state.StateDB) error { 217 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(block.Number().Int64())) 218 return nil 219 }, 220 OnFinalizeAndAssemble: func(header *types.Header, sdb *state.StateDB, txs []*types.Transaction) ([]byte, error) { 221 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(header.Number.Int64())) 222 return nil, nil 223 }, 224 }), 225 vm.Config{}, 226 lastAcceptedHash, 227 ) 228 if err != nil { 229 return nil, err 230 } 231 232 // Overwrite state manager, so that Shutdown is not called. 233 // This tests to ensure that the state manager handles an ungraceful shutdown correctly. 234 blockchain.stateManager = &wrappedStateManager{TrieWriter: blockchain.stateManager} 235 return blockchain, err 236 } 237 for _, tt := range tests { 238 t.Run(tt.Name, func(t *testing.T) { 239 tt.testFunc(t, create) 240 }) 241 } 242 } 243 244 func TestEnableSnapshots(t *testing.T) { 245 // Set snapshots to be disabled the first time, and then enable them on the restart 246 snapLimit := 0 247 create := func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error) { 248 // Import the chain. This runs all block validation rules. 249 blockchain, err := NewBlockChain( 250 db, 251 &CacheConfig{ 252 TrieCleanLimit: 256, 253 TrieDirtyLimit: 256, 254 Pruning: true, // Enable pruning 255 SnapshotLimit: snapLimit, // Disable snapshots 256 }, 257 chainConfig, 258 dummy.NewDummyEngine(&dummy.ConsensusCallbacks{ 259 OnExtraStateChange: func(block *types.Block, sdb *state.StateDB) error { 260 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(block.Number().Int64())) 261 return nil 262 }, 263 OnFinalizeAndAssemble: func(header *types.Header, sdb *state.StateDB, txs []*types.Transaction) ([]byte, error) { 264 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(header.Number.Int64())) 265 return nil, nil 266 }, 267 }), 268 vm.Config{}, 269 lastAcceptedHash, 270 ) 271 if err != nil { 272 return nil, err 273 } 274 snapLimit = 256 275 276 return blockchain, err 277 } 278 for _, tt := range tests { 279 t.Run(tt.Name, func(t *testing.T) { 280 tt.testFunc(t, create) 281 }) 282 } 283 } 284 285 func TestCorruptSnapshots(t *testing.T) { 286 create := func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error) { 287 // Delete the snapshot block hash and state root to ensure that if we die in between writing a snapshot 288 // diff layer to disk at any point, we can still recover on restart. 289 rawdb.DeleteSnapshotBlockHash(db) 290 rawdb.DeleteSnapshotRoot(db) 291 // Import the chain. This runs all block validation rules. 292 blockchain, err := NewBlockChain( 293 db, 294 &CacheConfig{ 295 TrieCleanLimit: 256, 296 TrieDirtyLimit: 256, 297 Pruning: true, // Enable pruning 298 SnapshotLimit: 256, // Disable snapshots 299 }, 300 chainConfig, 301 dummy.NewDummyEngine(&dummy.ConsensusCallbacks{ 302 OnExtraStateChange: func(block *types.Block, sdb *state.StateDB) error { 303 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(block.Number().Int64())) 304 return nil 305 }, 306 OnFinalizeAndAssemble: func(header *types.Header, sdb *state.StateDB, txs []*types.Transaction) ([]byte, error) { 307 sdb.SetBalanceMultiCoin(common.HexToAddress("0xdeadbeef"), common.HexToHash("0xdeadbeef"), big.NewInt(header.Number.Int64())) 308 return nil, nil 309 }, 310 }), 311 vm.Config{}, 312 lastAcceptedHash, 313 ) 314 if err != nil { 315 return nil, err 316 } 317 318 return blockchain, err 319 } 320 for _, tt := range tests { 321 t.Run(tt.Name, func(t *testing.T) { 322 tt.testFunc(t, create) 323 }) 324 } 325 }