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  }