forked from cerc-io/plugeth
Merge tag 'v1.10.22' into feature/merge-v1.10.22
This commit is contained in:
+10
-6
@@ -706,7 +706,7 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
|
||||
if block == nil {
|
||||
return fmt.Errorf("non existent block [%x..]", hash[:4])
|
||||
}
|
||||
if _, err := trie.NewSecure(common.Hash{}, block.Root(), bc.stateCache.TrieDB()); err != nil {
|
||||
if _, err := trie.NewStateTrie(common.Hash{}, block.Root(), bc.stateCache.TrieDB()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -893,6 +893,10 @@ func (bc *BlockChain) Stop() {
|
||||
log.Error("Dangling trie nodes after full cleanup")
|
||||
}
|
||||
}
|
||||
// Flush the collected preimages to disk
|
||||
if err := bc.stateCache.TrieDB().CommitPreimages(); err != nil {
|
||||
log.Error("Failed to commit trie preimages", "err", err)
|
||||
}
|
||||
// Ensure all live cached entries be saved into disk, so that we can skip
|
||||
// cache warmup when node restarts.
|
||||
if bc.cacheConfig.TrieCleanJournal != "" {
|
||||
@@ -1244,7 +1248,7 @@ func (bc *BlockChain) writeKnownBlock(block *types.Block) error {
|
||||
|
||||
// writeBlockWithState writes block, metadata and corresponding state data to the
|
||||
// database.
|
||||
func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB) error {
|
||||
func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, state *state.StateDB) error {
|
||||
// Calculate the total difficulty of the block
|
||||
ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1)
|
||||
if ptd == nil {
|
||||
@@ -1339,7 +1343,7 @@ func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types
|
||||
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
|
||||
// This function expects the chain mutex to be held.
|
||||
func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) {
|
||||
if err := bc.writeBlockWithState(block, receipts, logs, state); err != nil {
|
||||
if err := bc.writeBlockWithState(block, receipts, state); err != nil {
|
||||
return NonStatTy, err
|
||||
}
|
||||
currentBlock := bc.CurrentBlock()
|
||||
@@ -1380,7 +1384,7 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
|
||||
}
|
||||
// In theory we should fire a ChainHeadEvent when we inject
|
||||
// a canonical block, but sometimes we can insert a batch of
|
||||
// canonicial blocks. Avoid firing too many ChainHeadEvents,
|
||||
// canonical blocks. Avoid firing too many ChainHeadEvents,
|
||||
// we will fire an accumulated ChainHeadEvent and disable fire
|
||||
// event here.
|
||||
if emitHeadEvent {
|
||||
@@ -1618,7 +1622,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
|
||||
// block in the middle. It can only happen in the clique chain. Whenever
|
||||
// we insert blocks via `insertSideChain`, we only commit `td`, `header`
|
||||
// and `body` if it's non-existent. Since we don't have receipts without
|
||||
// reexecution, so nothing to commit. But if the sidechain will be adpoted
|
||||
// reexecution, so nothing to commit. But if the sidechain will be adopted
|
||||
// as the canonical chain eventually, it needs to be reexecuted for missing
|
||||
// state, but if it's this special case here(skip reexecution) we will lose
|
||||
// the empty receipt entry.
|
||||
@@ -1713,7 +1717,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
|
||||
var status WriteStatus
|
||||
if !setHead {
|
||||
// Don't set the head, only insert the block
|
||||
err = bc.writeBlockWithState(block, receipts, logs, statedb)
|
||||
err = bc.writeBlockWithState(block, receipts, statedb)
|
||||
} else {
|
||||
status, err = bc.writeBlockAndSetHead(block, receipts, logs, statedb, false)
|
||||
}
|
||||
|
||||
@@ -564,7 +564,7 @@ func testShortReorgedSnapSyncingRepair(t *testing.T, snapshots bool) {
|
||||
// Tests a recovery for a long canonical chain with frozen blocks where a recent
|
||||
// block - newer than the ancient limit - was already committed to disk and then
|
||||
// the process crashed. In this case we expect the chain to be rolled back to the
|
||||
// committed block, with everything afterwads kept as fast sync data.
|
||||
// committed block, with everything afterwards kept as fast sync data.
|
||||
func TestLongShallowRepair(t *testing.T) { testLongShallowRepair(t, false) }
|
||||
func TestLongShallowRepairWithSnapshots(t *testing.T) { testLongShallowRepair(t, true) }
|
||||
|
||||
@@ -609,7 +609,7 @@ func testLongShallowRepair(t *testing.T, snapshots bool) {
|
||||
// Tests a recovery for a long canonical chain with frozen blocks where a recent
|
||||
// block - older than the ancient limit - was already committed to disk and then
|
||||
// the process crashed. In this case we expect the chain to be rolled back to the
|
||||
// committed block, with everything afterwads deleted.
|
||||
// committed block, with everything afterwards deleted.
|
||||
func TestLongDeepRepair(t *testing.T) { testLongDeepRepair(t, false) }
|
||||
func TestLongDeepRepairWithSnapshots(t *testing.T) { testLongDeepRepair(t, true) }
|
||||
|
||||
@@ -653,7 +653,7 @@ func testLongDeepRepair(t *testing.T, snapshots bool) {
|
||||
// Tests a recovery for a long canonical chain with frozen blocks where the fast
|
||||
// sync pivot point - newer than the ancient limit - was already committed, after
|
||||
// which the process crashed. In this case we expect the chain to be rolled back
|
||||
// to the committed block, with everything afterwads kept as fast sync data.
|
||||
// to the committed block, with everything afterwards kept as fast sync data.
|
||||
func TestLongSnapSyncedShallowRepair(t *testing.T) {
|
||||
testLongSnapSyncedShallowRepair(t, false)
|
||||
}
|
||||
@@ -702,7 +702,7 @@ func testLongSnapSyncedShallowRepair(t *testing.T, snapshots bool) {
|
||||
// Tests a recovery for a long canonical chain with frozen blocks where the fast
|
||||
// sync pivot point - older than the ancient limit - was already committed, after
|
||||
// which the process crashed. In this case we expect the chain to be rolled back
|
||||
// to the committed block, with everything afterwads deleted.
|
||||
// to the committed block, with everything afterwards deleted.
|
||||
func TestLongSnapSyncedDeepRepair(t *testing.T) { testLongSnapSyncedDeepRepair(t, false) }
|
||||
func TestLongSnapSyncedDeepRepairWithSnapshots(t *testing.T) { testLongSnapSyncedDeepRepair(t, true) }
|
||||
|
||||
@@ -843,7 +843,7 @@ func testLongSnapSyncingDeepRepair(t *testing.T, snapshots bool) {
|
||||
// side chain, where a recent block - newer than the ancient limit - was already
|
||||
// committed to disk and then the process crashed. In this test scenario the side
|
||||
// chain is below the committed block. In this case we expect the chain to be
|
||||
// rolled back to the committed block, with everything afterwads kept as fast
|
||||
// rolled back to the committed block, with everything afterwards kept as fast
|
||||
// sync data; the side chain completely nuked by the freezer.
|
||||
func TestLongOldForkedShallowRepair(t *testing.T) {
|
||||
testLongOldForkedShallowRepair(t, false)
|
||||
@@ -895,7 +895,7 @@ func testLongOldForkedShallowRepair(t *testing.T, snapshots bool) {
|
||||
// side chain, where a recent block - older than the ancient limit - was already
|
||||
// committed to disk and then the process crashed. In this test scenario the side
|
||||
// chain is below the committed block. In this case we expect the canonical chain
|
||||
// to be rolled back to the committed block, with everything afterwads deleted;
|
||||
// to be rolled back to the committed block, with everything afterwards deleted;
|
||||
// the side chain completely nuked by the freezer.
|
||||
func TestLongOldForkedDeepRepair(t *testing.T) { testLongOldForkedDeepRepair(t, false) }
|
||||
func TestLongOldForkedDeepRepairWithSnapshots(t *testing.T) { testLongOldForkedDeepRepair(t, true) }
|
||||
@@ -942,7 +942,7 @@ func testLongOldForkedDeepRepair(t *testing.T, snapshots bool) {
|
||||
// side chain, where the fast sync pivot point - newer than the ancient limit -
|
||||
// was already committed to disk and then the process crashed. In this test scenario
|
||||
// the side chain is below the committed block. In this case we expect the chain
|
||||
// to be rolled back to the committed block, with everything afterwads kept as
|
||||
// to be rolled back to the committed block, with everything afterwards kept as
|
||||
// fast sync data; the side chain completely nuked by the freezer.
|
||||
func TestLongOldForkedSnapSyncedShallowRepair(t *testing.T) {
|
||||
testLongOldForkedSnapSyncedShallowRepair(t, false)
|
||||
@@ -994,7 +994,7 @@ func testLongOldForkedSnapSyncedShallowRepair(t *testing.T, snapshots bool) {
|
||||
// side chain, where the fast sync pivot point - older than the ancient limit -
|
||||
// was already committed to disk and then the process crashed. In this test scenario
|
||||
// the side chain is below the committed block. In this case we expect the canonical
|
||||
// chain to be rolled back to the committed block, with everything afterwads deleted;
|
||||
// chain to be rolled back to the committed block, with everything afterwards deleted;
|
||||
// the side chain completely nuked by the freezer.
|
||||
func TestLongOldForkedSnapSyncedDeepRepair(t *testing.T) {
|
||||
testLongOldForkedSnapSyncedDeepRepair(t, false)
|
||||
@@ -1149,7 +1149,7 @@ func testLongOldForkedSnapSyncingDeepRepair(t *testing.T, snapshots bool) {
|
||||
// side chain, where a recent block - newer than the ancient limit - was already
|
||||
// committed to disk and then the process crashed. In this test scenario the side
|
||||
// chain is above the committed block. In this case we expect the chain to be
|
||||
// rolled back to the committed block, with everything afterwads kept as fast
|
||||
// rolled back to the committed block, with everything afterwards kept as fast
|
||||
// sync data; the side chain completely nuked by the freezer.
|
||||
func TestLongNewerForkedShallowRepair(t *testing.T) {
|
||||
testLongNewerForkedShallowRepair(t, false)
|
||||
@@ -1201,7 +1201,7 @@ func testLongNewerForkedShallowRepair(t *testing.T, snapshots bool) {
|
||||
// side chain, where a recent block - older than the ancient limit - was already
|
||||
// committed to disk and then the process crashed. In this test scenario the side
|
||||
// chain is above the committed block. In this case we expect the canonical chain
|
||||
// to be rolled back to the committed block, with everything afterwads deleted;
|
||||
// to be rolled back to the committed block, with everything afterwards deleted;
|
||||
// the side chain completely nuked by the freezer.
|
||||
func TestLongNewerForkedDeepRepair(t *testing.T) { testLongNewerForkedDeepRepair(t, false) }
|
||||
func TestLongNewerForkedDeepRepairWithSnapshots(t *testing.T) { testLongNewerForkedDeepRepair(t, true) }
|
||||
@@ -1248,7 +1248,7 @@ func testLongNewerForkedDeepRepair(t *testing.T, snapshots bool) {
|
||||
// side chain, where the fast sync pivot point - newer than the ancient limit -
|
||||
// was already committed to disk and then the process crashed. In this test scenario
|
||||
// the side chain is above the committed block. In this case we expect the chain
|
||||
// to be rolled back to the committed block, with everything afterwads kept as fast
|
||||
// to be rolled back to the committed block, with everything afterwards kept as fast
|
||||
// sync data; the side chain completely nuked by the freezer.
|
||||
func TestLongNewerForkedSnapSyncedShallowRepair(t *testing.T) {
|
||||
testLongNewerForkedSnapSyncedShallowRepair(t, false)
|
||||
@@ -1300,7 +1300,7 @@ func testLongNewerForkedSnapSyncedShallowRepair(t *testing.T, snapshots bool) {
|
||||
// side chain, where the fast sync pivot point - older than the ancient limit -
|
||||
// was already committed to disk and then the process crashed. In this test scenario
|
||||
// the side chain is above the committed block. In this case we expect the canonical
|
||||
// chain to be rolled back to the committed block, with everything afterwads deleted;
|
||||
// chain to be rolled back to the committed block, with everything afterwards deleted;
|
||||
// the side chain completely nuked by the freezer.
|
||||
func TestLongNewerForkedSnapSyncedDeepRepair(t *testing.T) {
|
||||
testLongNewerForkedSnapSyncedDeepRepair(t, false)
|
||||
@@ -1454,7 +1454,7 @@ func testLongNewerForkedSnapSyncingDeepRepair(t *testing.T, snapshots bool) {
|
||||
// Tests a recovery for a long canonical chain with frozen blocks and a longer side
|
||||
// chain, where a recent block - newer than the ancient limit - was already committed
|
||||
// to disk and then the process crashed. In this case we expect the chain to be
|
||||
// rolled back to the committed block, with everything afterwads kept as fast sync
|
||||
// rolled back to the committed block, with everything afterwards kept as fast sync
|
||||
// data. The side chain completely nuked by the freezer.
|
||||
func TestLongReorgedShallowRepair(t *testing.T) { testLongReorgedShallowRepair(t, false) }
|
||||
func TestLongReorgedShallowRepairWithSnapshots(t *testing.T) { testLongReorgedShallowRepair(t, true) }
|
||||
@@ -1501,7 +1501,7 @@ func testLongReorgedShallowRepair(t *testing.T, snapshots bool) {
|
||||
// Tests a recovery for a long canonical chain with frozen blocks and a longer side
|
||||
// chain, where a recent block - older than the ancient limit - was already committed
|
||||
// to disk and then the process crashed. In this case we expect the canonical chains
|
||||
// to be rolled back to the committed block, with everything afterwads deleted. The
|
||||
// to be rolled back to the committed block, with everything afterwards deleted. The
|
||||
// side chain completely nuked by the freezer.
|
||||
func TestLongReorgedDeepRepair(t *testing.T) { testLongReorgedDeepRepair(t, false) }
|
||||
func TestLongReorgedDeepRepairWithSnapshots(t *testing.T) { testLongReorgedDeepRepair(t, true) }
|
||||
@@ -1548,7 +1548,7 @@ func testLongReorgedDeepRepair(t *testing.T, snapshots bool) {
|
||||
// side chain, where the fast sync pivot point - newer than the ancient limit -
|
||||
// was already committed to disk and then the process crashed. In this case we
|
||||
// expect the chain to be rolled back to the committed block, with everything
|
||||
// afterwads kept as fast sync data. The side chain completely nuked by the
|
||||
// afterwards kept as fast sync data. The side chain completely nuked by the
|
||||
// freezer.
|
||||
func TestLongReorgedSnapSyncedShallowRepair(t *testing.T) {
|
||||
testLongReorgedSnapSyncedShallowRepair(t, false)
|
||||
@@ -1600,7 +1600,7 @@ func testLongReorgedSnapSyncedShallowRepair(t *testing.T, snapshots bool) {
|
||||
// side chain, where the fast sync pivot point - older than the ancient limit -
|
||||
// was already committed to disk and then the process crashed. In this case we
|
||||
// expect the canonical chains to be rolled back to the committed block, with
|
||||
// everything afterwads deleted. The side chain completely nuked by the freezer.
|
||||
// everything afterwards deleted. The side chain completely nuked by the freezer.
|
||||
func TestLongReorgedSnapSyncedDeepRepair(t *testing.T) {
|
||||
testLongReorgedSnapSyncedDeepRepair(t, false)
|
||||
}
|
||||
|
||||
@@ -759,9 +759,9 @@ func TestFastVsFullChains(t *testing.T) {
|
||||
block.AddTx(tx)
|
||||
}
|
||||
}
|
||||
// If the block number is a multiple of 5, add a few bonus uncles to the block
|
||||
if i%5 == 5 {
|
||||
block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))})
|
||||
// If the block number is a multiple of 5, add an uncle to the block
|
||||
if i%5 == 4 {
|
||||
block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 2).Hash(), Number: big.NewInt(int64(i))})
|
||||
}
|
||||
})
|
||||
// Import the chain as an archive node for the comparison baseline
|
||||
@@ -1941,8 +1941,8 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
||||
Alloc: GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}},
|
||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||
}
|
||||
signer = types.LatestSigner(gspec.Config)
|
||||
genesis, _ = gspec.Commit(db)
|
||||
signer = types.LatestSigner(gspec.Config)
|
||||
genesis = gspec.MustCommit(db)
|
||||
)
|
||||
// Generate and import the canonical chain
|
||||
diskdb := rawdb.NewMemoryDatabase()
|
||||
|
||||
@@ -75,7 +75,7 @@ func (b *BloomIndexer) Process(ctx context.Context, header *types.Header) error
|
||||
// Commit implements core.ChainIndexerBackend, finalizing the bloom section and
|
||||
// writing it out into the database.
|
||||
func (b *BloomIndexer) Commit() error {
|
||||
batch := b.db.NewBatch()
|
||||
batch := b.db.NewBatchWithSize((int(b.size) / 8) * types.BloomBitLength)
|
||||
for i := 0; i < types.BloomBitLength; i++ {
|
||||
bits, err := b.gen.Bitset(uint(i))
|
||||
if err != nil {
|
||||
|
||||
+45
-39
@@ -80,10 +80,12 @@ func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// flush adds allocated genesis accounts into a fresh new statedb and
|
||||
// commit the state changes into the given database handler.
|
||||
func (ga *GenesisAlloc) flush(db ethdb.Database) (common.Hash, error) {
|
||||
statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil)
|
||||
// deriveHash computes the state root according to the genesis specification.
|
||||
func (ga *GenesisAlloc) deriveHash() (common.Hash, error) {
|
||||
// Create an ephemeral in-memory database for computing hash,
|
||||
// all the derived states will be discarded to not pollute disk.
|
||||
db := state.NewDatabase(rawdb.NewMemoryDatabase())
|
||||
statedb, err := state.New(common.Hash{}, db, nil)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
@@ -95,25 +97,39 @@ func (ga *GenesisAlloc) flush(db ethdb.Database) (common.Hash, error) {
|
||||
statedb.SetState(addr, key, value)
|
||||
}
|
||||
}
|
||||
return statedb.Commit(false)
|
||||
}
|
||||
|
||||
// flush is very similar with deriveHash, but the main difference is
|
||||
// all the generated states will be persisted into the given database.
|
||||
// Also, the genesis state specification will be flushed as well.
|
||||
func (ga *GenesisAlloc) flush(db ethdb.Database) error {
|
||||
statedb, err := state.New(common.Hash{}, state.NewDatabaseWithConfig(db, &trie.Config{Preimages: true}), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for addr, account := range *ga {
|
||||
statedb.AddBalance(addr, account.Balance)
|
||||
statedb.SetCode(addr, account.Code)
|
||||
statedb.SetNonce(addr, account.Nonce)
|
||||
for key, value := range account.Storage {
|
||||
statedb.SetState(addr, key, value)
|
||||
}
|
||||
}
|
||||
root, err := statedb.Commit(false)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
return err
|
||||
}
|
||||
err = statedb.Database().TrieDB().Commit(root, true, nil)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
return err
|
||||
}
|
||||
return root, nil
|
||||
}
|
||||
|
||||
// write writes the json marshaled genesis state into database
|
||||
// with the given block hash as the unique identifier.
|
||||
func (ga *GenesisAlloc) write(db ethdb.KeyValueWriter, hash common.Hash) error {
|
||||
// Marshal the genesis state specification and persist.
|
||||
blob, err := json.Marshal(ga)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rawdb.WriteGenesisState(db, hash, blob)
|
||||
rawdb.WriteGenesisStateSpec(db, root, blob)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -121,7 +137,7 @@ func (ga *GenesisAlloc) write(db ethdb.KeyValueWriter, hash common.Hash) error {
|
||||
// hash and commits them into the given database handler.
|
||||
func CommitGenesisState(db ethdb.Database, hash common.Hash) error {
|
||||
var alloc GenesisAlloc
|
||||
blob := rawdb.ReadGenesisState(db, hash)
|
||||
blob := rawdb.ReadGenesisStateSpec(db, hash)
|
||||
if len(blob) != 0 {
|
||||
if err := alloc.UnmarshalJSON(blob); err != nil {
|
||||
return err
|
||||
@@ -151,8 +167,7 @@ func CommitGenesisState(db ethdb.Database, hash common.Hash) error {
|
||||
return errors.New("not found")
|
||||
}
|
||||
}
|
||||
_, err := alloc.flush(db)
|
||||
return err
|
||||
return alloc.flush(db)
|
||||
}
|
||||
|
||||
// GenesisAccount is an account in the state of the genesis block.
|
||||
@@ -233,7 +248,7 @@ func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig
|
||||
return SetupGenesisBlockWithOverride(db, genesis, nil, nil)
|
||||
}
|
||||
|
||||
func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, overrideGrayGlacier, overrideTerminalTotalDifficulty *big.Int) (*params.ChainConfig, common.Hash, error) {
|
||||
func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, overrideTerminalTotalDifficulty *big.Int, overrideTerminalTotalDifficultyPassed *bool) (*params.ChainConfig, common.Hash, error) {
|
||||
if genesis != nil && genesis.Config == nil {
|
||||
return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig
|
||||
}
|
||||
@@ -243,8 +258,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override
|
||||
if overrideTerminalTotalDifficulty != nil {
|
||||
config.TerminalTotalDifficulty = overrideTerminalTotalDifficulty
|
||||
}
|
||||
if overrideGrayGlacier != nil {
|
||||
config.GrayGlacierBlock = overrideGrayGlacier
|
||||
if overrideTerminalTotalDifficultyPassed != nil {
|
||||
config.TerminalTotalDifficultyPassed = *overrideTerminalTotalDifficultyPassed
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -273,7 +288,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override
|
||||
genesis = DefaultGenesisBlock()
|
||||
}
|
||||
// Ensure the stored genesis matches with the given one.
|
||||
hash := genesis.ToBlock(nil).Hash()
|
||||
hash := genesis.ToBlock().Hash()
|
||||
if hash != stored {
|
||||
return genesis.Config, hash, &GenesisMismatchError{stored, hash}
|
||||
}
|
||||
@@ -286,7 +301,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override
|
||||
}
|
||||
// Check whether the genesis block is already written.
|
||||
if genesis != nil {
|
||||
hash := genesis.ToBlock(nil).Hash()
|
||||
hash := genesis.ToBlock().Hash()
|
||||
if hash != stored {
|
||||
return genesis.Config, hash, &GenesisMismatchError{stored, hash}
|
||||
}
|
||||
@@ -347,13 +362,9 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
|
||||
}
|
||||
}
|
||||
|
||||
// ToBlock creates the genesis block and writes state of a genesis specification
|
||||
// to the given database (or discards it if nil).
|
||||
func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
|
||||
if db == nil {
|
||||
db = rawdb.NewMemoryDatabase()
|
||||
}
|
||||
root, err := g.Alloc.flush(db)
|
||||
// ToBlock returns the genesis block according to genesis specification.
|
||||
func (g *Genesis) ToBlock() *types.Block {
|
||||
root, err := g.Alloc.deriveHash()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -390,7 +401,7 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
|
||||
// Commit writes the block and state of a genesis specification to the database.
|
||||
// The block is committed as the canonical head block.
|
||||
func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
|
||||
block := g.ToBlock(db)
|
||||
block := g.ToBlock()
|
||||
if block.Number().Sign() != 0 {
|
||||
return nil, errors.New("can't commit genesis block with number > 0")
|
||||
}
|
||||
@@ -404,7 +415,10 @@ func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
|
||||
if config.Clique != nil && len(block.Extra()) < 32+crypto.SignatureLength {
|
||||
return nil, errors.New("can't start clique chain without signers")
|
||||
}
|
||||
if err := g.Alloc.write(db, block.Hash()); err != nil {
|
||||
// All the checks has passed, flush the states derived from the genesis
|
||||
// specification as well as the specification itself into the provided
|
||||
// database.
|
||||
if err := g.Alloc.flush(db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty())
|
||||
@@ -428,15 +442,6 @@ func (g *Genesis) MustCommit(db ethdb.Database) *types.Block {
|
||||
return block
|
||||
}
|
||||
|
||||
// GenesisBlockForTesting creates and writes a block in which addr has the given wei balance.
|
||||
func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block {
|
||||
g := Genesis{
|
||||
Alloc: GenesisAlloc{addr: {Balance: balance}},
|
||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||
}
|
||||
return g.MustCommit(db)
|
||||
}
|
||||
|
||||
// DefaultGenesisBlock returns the Ethereum main net genesis block.
|
||||
func DefaultGenesisBlock() *Genesis {
|
||||
return &Genesis{
|
||||
@@ -498,6 +503,7 @@ func DefaultSepoliaGenesisBlock() *Genesis {
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultKilnGenesisBlock returns the kiln network genesis block.
|
||||
func DefaultKilnGenesisBlock() *Genesis {
|
||||
g := new(Genesis)
|
||||
reader := strings.NewReader(KilnAllocData)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -178,7 +178,7 @@ func TestGenesisHashes(t *testing.T) {
|
||||
t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex())
|
||||
}
|
||||
// Test via ToBlock
|
||||
if have := c.genesis.ToBlock(nil).Hash(); have != c.want {
|
||||
if have := c.genesis.ToBlock().Hash(); have != c.want {
|
||||
t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex())
|
||||
}
|
||||
}
|
||||
@@ -192,11 +192,7 @@ func TestGenesis_Commit(t *testing.T) {
|
||||
}
|
||||
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
genesisBlock, err := genesis.Commit(db)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
genesisBlock := genesis.MustCommit(db)
|
||||
if genesis.Difficulty != nil {
|
||||
t.Fatalf("assumption wrong")
|
||||
}
|
||||
@@ -221,12 +217,12 @@ func TestReadWriteGenesisAlloc(t *testing.T) {
|
||||
{1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
|
||||
{2}: {Balance: big.NewInt(2), Storage: map[common.Hash]common.Hash{{2}: {2}}},
|
||||
}
|
||||
hash = common.HexToHash("0xdeadbeef")
|
||||
hash, _ = alloc.deriveHash()
|
||||
)
|
||||
alloc.write(db, hash)
|
||||
alloc.flush(db)
|
||||
|
||||
var reload GenesisAlloc
|
||||
err := reload.UnmarshalJSON(rawdb.ReadGenesisState(db, hash))
|
||||
err := reload.UnmarshalJSON(rawdb.ReadGenesisStateSpec(db, hash))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load genesis state %v", err)
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ import (
|
||||
func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash {
|
||||
var data []byte
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
data, _ = reader.Ancient(freezerHashTable, number)
|
||||
data, _ = reader.Ancient(chainFreezerHashTable, number)
|
||||
if len(data) == 0 {
|
||||
// Get it by hash from leveldb
|
||||
data, _ = db.Get(headerHashKey(number))
|
||||
@@ -335,7 +335,7 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu
|
||||
}
|
||||
// read remaining from ancients
|
||||
max := count * 700
|
||||
data, err := db.AncientRange(freezerHeaderTable, i+1-count, count, max)
|
||||
data, err := db.AncientRange(chainFreezerHeaderTable, i+1-count, count, max)
|
||||
if err == nil && uint64(len(data)) == count {
|
||||
// the data is on the order [h, h+1, .., n] -- reordering needed
|
||||
for i := range data {
|
||||
@@ -352,7 +352,7 @@ func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValu
|
||||
// First try to look up the data in ancient database. Extra hash
|
||||
// comparison is necessary since ancient database only maintains
|
||||
// the canonical data.
|
||||
data, _ = reader.Ancient(freezerHeaderTable, number)
|
||||
data, _ = reader.Ancient(chainFreezerHeaderTable, number)
|
||||
if len(data) > 0 && crypto.Keccak256Hash(data) == hash {
|
||||
return nil
|
||||
}
|
||||
@@ -428,7 +428,7 @@ func deleteHeaderWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number
|
||||
// isCanon is an internal utility method, to check whether the given number/hash
|
||||
// is part of the ancient (canon) set.
|
||||
func isCanon(reader ethdb.AncientReaderOp, number uint64, hash common.Hash) bool {
|
||||
h, err := reader.Ancient(freezerHashTable, number)
|
||||
h, err := reader.Ancient(chainFreezerHashTable, number)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
@@ -444,7 +444,7 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
// Check if the data is in ancients
|
||||
if isCanon(reader, number, hash) {
|
||||
data, _ = reader.Ancient(freezerBodiesTable, number)
|
||||
data, _ = reader.Ancient(chainFreezerBodiesTable, number)
|
||||
return nil
|
||||
}
|
||||
// If not, try reading from leveldb
|
||||
@@ -459,7 +459,7 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue
|
||||
func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue {
|
||||
var data []byte
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
data, _ = reader.Ancient(freezerBodiesTable, number)
|
||||
data, _ = reader.Ancient(chainFreezerBodiesTable, number)
|
||||
if len(data) > 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -527,7 +527,7 @@ func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
// Check if the data is in ancients
|
||||
if isCanon(reader, number, hash) {
|
||||
data, _ = reader.Ancient(freezerDifficultyTable, number)
|
||||
data, _ = reader.Ancient(chainFreezerDifficultyTable, number)
|
||||
return nil
|
||||
}
|
||||
// If not, try reading from leveldb
|
||||
@@ -587,7 +587,7 @@ func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawVa
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
// Check if the data is in ancients
|
||||
if isCanon(reader, number, hash) {
|
||||
data, _ = reader.Ancient(freezerReceiptTable, number)
|
||||
data, _ = reader.Ancient(chainFreezerReceiptTable, number)
|
||||
return nil
|
||||
}
|
||||
// If not, try reading from leveldb
|
||||
@@ -819,19 +819,19 @@ func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts
|
||||
|
||||
func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *types.Header, receipts []*types.ReceiptForStorage, td *big.Int) error {
|
||||
num := block.NumberU64()
|
||||
if err := op.AppendRaw(freezerHashTable, num, block.Hash().Bytes()); err != nil {
|
||||
if err := op.AppendRaw(chainFreezerHashTable, num, block.Hash().Bytes()); err != nil {
|
||||
return fmt.Errorf("can't add block %d hash: %v", num, err)
|
||||
}
|
||||
if err := op.Append(freezerHeaderTable, num, header); err != nil {
|
||||
if err := op.Append(chainFreezerHeaderTable, num, header); err != nil {
|
||||
return fmt.Errorf("can't append block header %d: %v", num, err)
|
||||
}
|
||||
if err := op.Append(freezerBodiesTable, num, block.Body()); err != nil {
|
||||
if err := op.Append(chainFreezerBodiesTable, num, block.Body()); err != nil {
|
||||
return fmt.Errorf("can't append block body %d: %v", num, err)
|
||||
}
|
||||
if err := op.Append(freezerReceiptTable, num, receipts); err != nil {
|
||||
if err := op.Append(chainFreezerReceiptTable, num, receipts); err != nil {
|
||||
return fmt.Errorf("can't append block %d receipts: %v", num, err)
|
||||
}
|
||||
if err := op.Append(freezerDifficultyTable, num, td); err != nil {
|
||||
if err := op.Append(chainFreezerDifficultyTable, num, td); err != nil {
|
||||
return fmt.Errorf("can't append block %d total difficulty: %v", num, err)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -285,7 +285,7 @@ func TestTdStorage(t *testing.T) {
|
||||
func TestCanonicalMappingStorage(t *testing.T) {
|
||||
db := NewMemoryDatabase()
|
||||
|
||||
// Create a test canonical number and assinged hash to move around
|
||||
// Create a test canonical number and assigned hash to move around
|
||||
hash, number := common.Hash{0: 0xff}, uint64(314)
|
||||
if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) {
|
||||
t.Fatalf("Non existent canonical mapping returned: %v", entry)
|
||||
|
||||
@@ -81,15 +81,16 @@ func WriteChainConfig(db ethdb.KeyValueWriter, hash common.Hash, cfg *params.Cha
|
||||
}
|
||||
}
|
||||
|
||||
// ReadGenesisState retrieves the genesis state based on the given genesis hash.
|
||||
func ReadGenesisState(db ethdb.KeyValueReader, hash common.Hash) []byte {
|
||||
data, _ := db.Get(genesisKey(hash))
|
||||
// ReadGenesisStateSpec retrieves the genesis state specification based on the
|
||||
// given genesis hash.
|
||||
func ReadGenesisStateSpec(db ethdb.KeyValueReader, hash common.Hash) []byte {
|
||||
data, _ := db.Get(genesisStateSpecKey(hash))
|
||||
return data
|
||||
}
|
||||
|
||||
// WriteGenesisState writes the genesis state into the disk.
|
||||
func WriteGenesisState(db ethdb.KeyValueWriter, hash common.Hash, data []byte) {
|
||||
if err := db.Put(genesisKey(hash), data); err != nil {
|
||||
// WriteGenesisStateSpec writes the genesis state specification into the disk.
|
||||
func WriteGenesisStateSpec(db ethdb.KeyValueWriter, hash common.Hash, data []byte) {
|
||||
if err := db.Put(genesisStateSpecKey(hash), data); err != nil {
|
||||
log.Crit("Failed to store genesis state", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
// Copyright 2022 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package rawdb
|
||||
|
||||
import "fmt"
|
||||
|
||||
// The list of table names of chain freezer.
|
||||
const (
|
||||
// chainFreezerHeaderTable indicates the name of the freezer header table.
|
||||
chainFreezerHeaderTable = "headers"
|
||||
|
||||
// chainFreezerHashTable indicates the name of the freezer canonical hash table.
|
||||
chainFreezerHashTable = "hashes"
|
||||
|
||||
// chainFreezerBodiesTable indicates the name of the freezer block body table.
|
||||
chainFreezerBodiesTable = "bodies"
|
||||
|
||||
// chainFreezerReceiptTable indicates the name of the freezer receipts table.
|
||||
chainFreezerReceiptTable = "receipts"
|
||||
|
||||
// chainFreezerDifficultyTable indicates the name of the freezer total difficulty table.
|
||||
chainFreezerDifficultyTable = "diffs"
|
||||
)
|
||||
|
||||
// chainFreezerNoSnappy configures whether compression is disabled for the ancient-tables.
|
||||
// Hashes and difficulties don't compress well.
|
||||
var chainFreezerNoSnappy = map[string]bool{
|
||||
chainFreezerHeaderTable: false,
|
||||
chainFreezerHashTable: true,
|
||||
chainFreezerBodiesTable: false,
|
||||
chainFreezerReceiptTable: false,
|
||||
chainFreezerDifficultyTable: true,
|
||||
}
|
||||
|
||||
// The list of identifiers of ancient stores.
|
||||
var (
|
||||
chainFreezerName = "chain" // the folder name of chain segment ancient store.
|
||||
)
|
||||
|
||||
// freezers the collections of all builtin freezers.
|
||||
var freezers = []string{chainFreezerName}
|
||||
|
||||
// InspectFreezerTable dumps out the index of a specific freezer table. The passed
|
||||
// ancient indicates the path of root ancient directory where the chain freezer can
|
||||
// be opened. Start and end specify the range for dumping out indexes.
|
||||
// Note this function can only be used for debugging purposes.
|
||||
func InspectFreezerTable(ancient string, freezerName string, tableName string, start, end int64) error {
|
||||
var (
|
||||
path string
|
||||
tables map[string]bool
|
||||
)
|
||||
switch freezerName {
|
||||
case chainFreezerName:
|
||||
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
|
||||
default:
|
||||
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
|
||||
}
|
||||
noSnappy, exist := tables[tableName]
|
||||
if !exist {
|
||||
var names []string
|
||||
for name := range tables {
|
||||
names = append(names, name)
|
||||
}
|
||||
return fmt.Errorf("unknown table, supported ones: %v", names)
|
||||
}
|
||||
table, err := newFreezerTable(path, tableName, noSnappy, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
table.dumpIndexStdout(start, end)
|
||||
return nil
|
||||
}
|
||||
@@ -241,7 +241,7 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
|
||||
if n := len(ancients); n > 0 {
|
||||
context = append(context, []interface{}{"hash", ancients[n-1]}...)
|
||||
}
|
||||
log.Info("Deep froze chain segment", context...)
|
||||
log.Debug("Deep froze chain segment", context...)
|
||||
|
||||
// Avoid database thrashing with tiny writes
|
||||
if frozen-first < freezerBatchLimit {
|
||||
@@ -278,19 +278,19 @@ func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hash
|
||||
}
|
||||
|
||||
// Write to the batch.
|
||||
if err := op.AppendRaw(freezerHashTable, number, hash[:]); err != nil {
|
||||
if err := op.AppendRaw(chainFreezerHashTable, number, hash[:]); err != nil {
|
||||
return fmt.Errorf("can't write hash to Freezer: %v", err)
|
||||
}
|
||||
if err := op.AppendRaw(freezerHeaderTable, number, header); err != nil {
|
||||
if err := op.AppendRaw(chainFreezerHeaderTable, number, header); err != nil {
|
||||
return fmt.Errorf("can't write header to Freezer: %v", err)
|
||||
}
|
||||
if err := op.AppendRaw(freezerBodiesTable, number, body); err != nil {
|
||||
if err := op.AppendRaw(chainFreezerBodiesTable, number, body); err != nil {
|
||||
return fmt.Errorf("can't write body to Freezer: %v", err)
|
||||
}
|
||||
if err := op.AppendRaw(freezerReceiptTable, number, receipts); err != nil {
|
||||
if err := op.AppendRaw(chainFreezerReceiptTable, number, receipts); err != nil {
|
||||
return fmt.Errorf("can't write receipts to Freezer: %v", err)
|
||||
}
|
||||
if err := op.AppendRaw(freezerDifficultyTable, number, td); err != nil {
|
||||
if err := op.AppendRaw(chainFreezerDifficultyTable, number, td); err != nil {
|
||||
return fmt.Errorf("can't write td to Freezer: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ func InitDatabaseFromFreezer(db ethdb.Database) {
|
||||
if i+count > frozen {
|
||||
count = frozen - i
|
||||
}
|
||||
data, err := db.AncientRange(freezerHashTable, i, count, 32*count)
|
||||
data, err := db.AncientRange(chainFreezerHashTable, i, count, 32*count)
|
||||
if err != nil {
|
||||
log.Crit("Failed to init database from freezer", "err", err)
|
||||
}
|
||||
|
||||
+43
-9
@@ -21,6 +21,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
@@ -34,10 +35,16 @@ import (
|
||||
|
||||
// freezerdb is a database wrapper that enabled freezer data retrievals.
|
||||
type freezerdb struct {
|
||||
ancientRoot string
|
||||
ethdb.KeyValueStore
|
||||
ethdb.AncientStore
|
||||
}
|
||||
|
||||
// AncientDatadir returns the path of root ancient directory.
|
||||
func (frdb *freezerdb) AncientDatadir() (string, error) {
|
||||
return frdb.ancientRoot, nil
|
||||
}
|
||||
|
||||
// Close implements io.Closer, closing both the fast key-value store as well as
|
||||
// the slow ancient tables.
|
||||
func (frdb *freezerdb) Close() error {
|
||||
@@ -162,12 +169,36 @@ func NewDatabase(db ethdb.KeyValueStore) ethdb.Database {
|
||||
return &nofreezedb{KeyValueStore: db}
|
||||
}
|
||||
|
||||
// resolveChainFreezerDir is a helper function which resolves the absolute path
|
||||
// of chain freezer by considering backward compatibility.
|
||||
func resolveChainFreezerDir(ancient string) string {
|
||||
// Check if the chain freezer is already present in the specified
|
||||
// sub folder, if not then two possibilities:
|
||||
// - chain freezer is not initialized
|
||||
// - chain freezer exists in legacy location (root ancient folder)
|
||||
freezer := path.Join(ancient, chainFreezerName)
|
||||
if !common.FileExist(freezer) {
|
||||
if !common.FileExist(ancient) {
|
||||
// The entire ancient store is not initialized, still use the sub
|
||||
// folder for initialization.
|
||||
} else {
|
||||
// Ancient root is already initialized, then we hold the assumption
|
||||
// that chain freezer is also initialized and located in root folder.
|
||||
// In this case fallback to legacy location.
|
||||
freezer = ancient
|
||||
log.Info("Found legacy ancient chain path", "location", ancient)
|
||||
}
|
||||
}
|
||||
return freezer
|
||||
}
|
||||
|
||||
// NewDatabaseWithFreezer creates a high level database on top of a given key-
|
||||
// value data store with a freezer moving immutable chain segments into cold
|
||||
// storage.
|
||||
func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace string, readonly bool) (ethdb.Database, error) {
|
||||
// storage. The passed ancient indicates the path of root ancient directory
|
||||
// where the chain freezer can be opened.
|
||||
func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace string, readonly bool) (ethdb.Database, error) {
|
||||
// Create the idle freezer instance
|
||||
frdb, err := newChainFreezer(freezer, namespace, readonly, freezerTableSize, FreezerNoSnappy)
|
||||
frdb, err := newChainFreezer(resolveChainFreezerDir(ancient), namespace, readonly, freezerTableSize, chainFreezerNoSnappy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -198,7 +229,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace st
|
||||
// If the freezer already contains something, ensure that the genesis blocks
|
||||
// match, otherwise we might mix up freezers across chains and destroy both
|
||||
// the freezer and the key-value store.
|
||||
frgenesis, err := frdb.Ancient(freezerHashTable, 0)
|
||||
frgenesis, err := frdb.Ancient(chainFreezerHashTable, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err)
|
||||
} else if !bytes.Equal(kvgenesis, frgenesis) {
|
||||
@@ -229,7 +260,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace st
|
||||
if kvblob, _ := db.Get(headerHashKey(1)); len(kvblob) == 0 {
|
||||
return nil, errors.New("ancient chain segments already extracted, please set --datadir.ancient to the correct path")
|
||||
}
|
||||
// Block #1 is still in the database, we're allowed to init a new feezer
|
||||
// Block #1 is still in the database, we're allowed to init a new freezer
|
||||
}
|
||||
// Otherwise, the head header is still the genesis, we're allowed to init a new
|
||||
// freezer.
|
||||
@@ -244,6 +275,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace st
|
||||
}()
|
||||
}
|
||||
return &freezerdb{
|
||||
ancientRoot: ancient,
|
||||
KeyValueStore: db,
|
||||
AncientStore: frdb,
|
||||
}, nil
|
||||
@@ -273,13 +305,15 @@ func NewLevelDBDatabase(file string, cache int, handles int, namespace string, r
|
||||
}
|
||||
|
||||
// NewLevelDBDatabaseWithFreezer creates a persistent key-value database with a
|
||||
// freezer moving immutable chain segments into cold storage.
|
||||
func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, freezer string, namespace string, readonly bool) (ethdb.Database, error) {
|
||||
// freezer moving immutable chain segments into cold storage. The passed ancient
|
||||
// indicates the path of root ancient directory where the chain freezer can be
|
||||
// opened.
|
||||
func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, ancient string, namespace string, readonly bool) (ethdb.Database, error) {
|
||||
kvdb, err := leveldb.New(file, cache, handles, namespace, readonly)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frdb, err := NewDatabaseWithFreezer(kvdb, freezer, namespace, readonly)
|
||||
frdb, err := NewDatabaseWithFreezer(kvdb, ancient, namespace, readonly)
|
||||
if err != nil {
|
||||
kvdb.Close()
|
||||
return nil, err
|
||||
@@ -441,7 +475,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
||||
}
|
||||
// Inspect append-only file store then.
|
||||
ancientSizes := []*common.StorageSize{&ancientHeadersSize, &ancientBodiesSize, &ancientReceiptsSize, &ancientHashesSize, &ancientTdsSize}
|
||||
for i, category := range []string{freezerHeaderTable, freezerBodiesTable, freezerReceiptTable, freezerHashTable, freezerDifficultyTable} {
|
||||
for i, category := range []string{chainFreezerHeaderTable, chainFreezerBodiesTable, chainFreezerReceiptTable, chainFreezerHashTable, chainFreezerDifficultyTable} {
|
||||
if size, err := db.AncientSize(category); err == nil {
|
||||
*ancientSizes[i] += common.StorageSize(size)
|
||||
total += common.StorageSize(size)
|
||||
|
||||
+1
-10
@@ -68,8 +68,6 @@ type Freezer struct {
|
||||
frozen uint64 // Number of blocks already frozen
|
||||
tail uint64 // Number of the first stored item in the freezer
|
||||
|
||||
datadir string // Path of root directory of ancient store
|
||||
|
||||
// This lock synchronizes writers and the truncate operation, as well as
|
||||
// the "atomic" (batched) read operations.
|
||||
writeLock sync.RWMutex
|
||||
@@ -111,7 +109,6 @@ func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize ui
|
||||
readonly: readonly,
|
||||
tables: make(map[string]*freezerTable),
|
||||
instanceLock: lock,
|
||||
datadir: datadir,
|
||||
}
|
||||
|
||||
// Create the tables.
|
||||
@@ -432,7 +429,7 @@ func (f *Freezer) MigrateTable(kind string, convert convertLegacyFn) error {
|
||||
// Set up new dir for the migrated table, the content of which
|
||||
// we'll at the end move over to the ancients dir.
|
||||
migrationPath := filepath.Join(ancientsPath, "migration")
|
||||
newTable, err := NewFreezerTable(migrationPath, kind, table.noCompression, false)
|
||||
newTable, err := newFreezerTable(migrationPath, kind, table.noCompression, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -489,11 +486,5 @@ func (f *Freezer) MigrateTable(kind string, convert convertLegacyFn) error {
|
||||
if err := os.Remove(migrationPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AncientDatadir returns the root directory path of the ancient store.
|
||||
func (f *Freezer) AncientDatadir() (string, error) {
|
||||
return f.datadir, nil
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ var (
|
||||
errNotSupported = errors.New("this operation is not supported")
|
||||
)
|
||||
|
||||
// indexEntry contains the number/id of the file that the data resides in, aswell as the
|
||||
// indexEntry contains the number/id of the file that the data resides in, as well as the
|
||||
// offset within the file to the end of the data.
|
||||
// In serialized form, the filenum is stored as uint16.
|
||||
type indexEntry struct {
|
||||
@@ -123,8 +123,8 @@ type freezerTable struct {
|
||||
lock sync.RWMutex // Mutex protecting the data file descriptors
|
||||
}
|
||||
|
||||
// NewFreezerTable opens the given path as a freezer table.
|
||||
func NewFreezerTable(path, name string, disableSnappy, readonly bool) (*freezerTable, error) {
|
||||
// newFreezerTable opens the given path as a freezer table.
|
||||
func newFreezerTable(path, name string, disableSnappy, readonly bool) (*freezerTable, error) {
|
||||
return newTable(path, name, metrics.NilMeter{}, metrics.NilMeter{}, metrics.NilGauge{}, freezerTableSize, disableSnappy, readonly)
|
||||
}
|
||||
|
||||
@@ -884,9 +884,7 @@ func (t *freezerTable) Sync() error {
|
||||
return t.head.Sync()
|
||||
}
|
||||
|
||||
// DumpIndex is a debug print utility function, mainly for testing. It can also
|
||||
// be used to analyse a live freezer table index.
|
||||
func (t *freezerTable) DumpIndex(start, stop int64) {
|
||||
func (t *freezerTable) dumpIndexStdout(start, stop int64) {
|
||||
t.dumpIndex(os.Stdout, start, stop)
|
||||
}
|
||||
|
||||
|
||||
@@ -902,7 +902,7 @@ func TestSequentialRead(t *testing.T) {
|
||||
}
|
||||
// Write 15 bytes 30 times
|
||||
writeChunks(t, f, 30, 15)
|
||||
f.DumpIndex(0, 30)
|
||||
f.dumpIndexStdout(0, 30)
|
||||
f.Close()
|
||||
}
|
||||
{ // Open it, iterate, verify iteration
|
||||
|
||||
+56
-56
@@ -4,7 +4,7 @@ package rawdb
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
// "github.com/ethereum/go-ethereum/rlp"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -57,64 +57,64 @@ func PluginCommitUpdate(pl *plugins.PluginLoader, num uint64) {
|
||||
fn(i, update)
|
||||
}
|
||||
}
|
||||
appendAncientFnList := pl.Lookup("AppendAncient", func(item interface{}) bool {
|
||||
_ = pl.Lookup("AppendAncient", func(item interface{}) bool {
|
||||
_, ok := item.(func(number uint64, hash, header, body, receipts, td []byte))
|
||||
if ok { log.Warn("PlugEth's AppendAncient is deprecated. Please update to ModifyAncients.") }
|
||||
return ok
|
||||
})
|
||||
if len(appendAncientFnList) > 0 {
|
||||
var (
|
||||
hash []byte
|
||||
header []byte
|
||||
body []byte
|
||||
receipts []byte
|
||||
td []byte
|
||||
)
|
||||
if hashi, ok := update[freezerHashTable]; ok {
|
||||
switch v := hashi.(type) {
|
||||
case []byte:
|
||||
hash = v
|
||||
default:
|
||||
hash, _ = rlp.EncodeToBytes(v)
|
||||
}
|
||||
}
|
||||
if headeri, ok := update[freezerHeaderTable]; ok {
|
||||
switch v := headeri.(type) {
|
||||
case []byte:
|
||||
header = v
|
||||
default:
|
||||
header, _ = rlp.EncodeToBytes(v)
|
||||
}
|
||||
}
|
||||
if bodyi, ok := update[freezerBodiesTable]; ok {
|
||||
switch v := bodyi.(type) {
|
||||
case []byte:
|
||||
body = v
|
||||
default:
|
||||
body, _ = rlp.EncodeToBytes(v)
|
||||
}
|
||||
}
|
||||
if receiptsi, ok := update[freezerReceiptTable]; ok {
|
||||
switch v := receiptsi.(type) {
|
||||
case []byte:
|
||||
receipts = v
|
||||
default:
|
||||
receipts, _ = rlp.EncodeToBytes(v)
|
||||
}
|
||||
}
|
||||
if tdi, ok := update[freezerDifficultyTable]; ok {
|
||||
switch v := tdi.(type) {
|
||||
case []byte:
|
||||
td = v
|
||||
default:
|
||||
td, _ = rlp.EncodeToBytes(v)
|
||||
}
|
||||
}
|
||||
for _, fni := range appendAncientFnList {
|
||||
if fn, ok := fni.(func(number uint64, hash, header, body, receipts, td []byte)); ok {
|
||||
fn(i, hash, header, body, receipts, td)
|
||||
}
|
||||
}
|
||||
}
|
||||
// if len(appendAncientFnList) > 0 {
|
||||
// var (
|
||||
// hash []byte
|
||||
// header []byte
|
||||
// body []byte
|
||||
// receipts []byte
|
||||
// td []byte
|
||||
// )
|
||||
// if hashi, ok := update[freezerHashTable]; ok {
|
||||
// switch v := hashi.(type) {
|
||||
// case []byte:
|
||||
// hash = v
|
||||
// default:
|
||||
// hash, _ = rlp.EncodeToBytes(v)
|
||||
// }
|
||||
// }
|
||||
// if headeri, ok := update[freezerHeaderTable]; ok {
|
||||
// switch v := headeri.(type) {
|
||||
// case []byte:
|
||||
// header = v
|
||||
// default:
|
||||
// header, _ = rlp.EncodeToBytes(v)
|
||||
// }
|
||||
// }
|
||||
// if bodyi, ok := update[freezerBodiesTable]; ok {
|
||||
// switch v := bodyi.(type) {
|
||||
// case []byte:
|
||||
// body = v
|
||||
// default:
|
||||
// body, _ = rlp.EncodeToBytes(v)
|
||||
// }
|
||||
// }
|
||||
// if receiptsi, ok := update[freezerReceiptTable]; ok {
|
||||
// switch v := receiptsi.(type) {
|
||||
// case []byte:
|
||||
// receipts = v
|
||||
// default:
|
||||
// receipts, _ = rlp.EncodeToBytes(v)
|
||||
// }
|
||||
// }
|
||||
// if tdi, ok := update[freezerDifficultyTable]; ok {
|
||||
// switch v := tdi.(type) {
|
||||
// case []byte:
|
||||
// td = v
|
||||
// default:
|
||||
// td, _ = rlp.EncodeToBytes(v)
|
||||
// }
|
||||
// }
|
||||
// for _, fni := range appendAncientFnList {
|
||||
// if fn, ok := fni.(func(number uint64, hash, header, body, receipts, td []byte)); ok {
|
||||
// fn(i, hash, header, body, receipts, td)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
+2
-29
@@ -111,33 +111,6 @@ var (
|
||||
preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil)
|
||||
)
|
||||
|
||||
const (
|
||||
// freezerHeaderTable indicates the name of the freezer header table.
|
||||
freezerHeaderTable = "headers"
|
||||
|
||||
// freezerHashTable indicates the name of the freezer canonical hash table.
|
||||
freezerHashTable = "hashes"
|
||||
|
||||
// freezerBodiesTable indicates the name of the freezer block body table.
|
||||
freezerBodiesTable = "bodies"
|
||||
|
||||
// freezerReceiptTable indicates the name of the freezer receipts table.
|
||||
freezerReceiptTable = "receipts"
|
||||
|
||||
// freezerDifficultyTable indicates the name of the freezer total difficulty table.
|
||||
freezerDifficultyTable = "diffs"
|
||||
)
|
||||
|
||||
// FreezerNoSnappy configures whether compression is disabled for the ancient-tables.
|
||||
// Hashes and difficulties don't compress well.
|
||||
var FreezerNoSnappy = map[string]bool{
|
||||
freezerHeaderTable: false,
|
||||
freezerHashTable: true,
|
||||
freezerBodiesTable: false,
|
||||
freezerReceiptTable: false,
|
||||
freezerDifficultyTable: true,
|
||||
}
|
||||
|
||||
// LegacyTxLookupEntry is the legacy TxLookupEntry definition with some unnecessary
|
||||
// fields.
|
||||
type LegacyTxLookupEntry struct {
|
||||
@@ -247,7 +220,7 @@ func configKey(hash common.Hash) []byte {
|
||||
return append(configPrefix, hash.Bytes()...)
|
||||
}
|
||||
|
||||
// genesisKey = genesisPrefix + hash
|
||||
func genesisKey(hash common.Hash) []byte {
|
||||
// genesisStateSpecKey = genesisPrefix + hash
|
||||
func genesisStateSpecKey(hash common.Hash) []byte {
|
||||
return append(genesisPrefix, hash.Bytes()...)
|
||||
}
|
||||
|
||||
+19
-9
@@ -63,7 +63,7 @@ type Trie interface {
|
||||
// GetKey returns the sha3 preimage of a hashed key that was previously used
|
||||
// to store a value.
|
||||
//
|
||||
// TODO(fjl): remove this when SecureTrie is removed
|
||||
// TODO(fjl): remove this when StateTrie is removed
|
||||
GetKey([]byte) []byte
|
||||
|
||||
// TryGet returns the value for key stored in the trie. The value bytes must
|
||||
@@ -71,8 +71,8 @@ type Trie interface {
|
||||
// trie.MissingNodeError is returned.
|
||||
TryGet(key []byte) ([]byte, error)
|
||||
|
||||
// TryUpdateAccount abstract an account write in the trie.
|
||||
TryUpdateAccount(key []byte, account *types.StateAccount) error
|
||||
// TryGetAccount abstract an account read from the trie.
|
||||
TryGetAccount(key []byte) (*types.StateAccount, error)
|
||||
|
||||
// TryUpdate associates key with value in the trie. If value has length zero, any
|
||||
// existing value is deleted from the trie. The value bytes must not be modified
|
||||
@@ -80,17 +80,27 @@ type Trie interface {
|
||||
// database, a trie.MissingNodeError is returned.
|
||||
TryUpdate(key, value []byte) error
|
||||
|
||||
// TryUpdateAccount abstract an account write to the trie.
|
||||
TryUpdateAccount(key []byte, account *types.StateAccount) error
|
||||
|
||||
// TryDelete removes any existing value for key from the trie. If a node was not
|
||||
// found in the database, a trie.MissingNodeError is returned.
|
||||
TryDelete(key []byte) error
|
||||
|
||||
// TryDeleteAccount abstracts an account deletion from the trie.
|
||||
TryDeleteAccount(key []byte) error
|
||||
|
||||
// Hash returns the root hash of the trie. It does not write to the database and
|
||||
// can be used even if the trie doesn't have one.
|
||||
Hash() common.Hash
|
||||
|
||||
// Commit writes all nodes to the trie's memory database, tracking the internal
|
||||
// and external (for account tries) references.
|
||||
Commit(onleaf trie.LeafCallback) (common.Hash, int, error)
|
||||
// Commit collects all dirty nodes in the trie and replace them with the
|
||||
// corresponding node hash. All collected nodes(including dirty leaves if
|
||||
// collectLeaf is true) will be encapsulated into a nodeset for return.
|
||||
// The returned nodeset can be nil if the trie is clean(nothing to commit).
|
||||
// Once the trie is committed, it's not usable anymore. A new trie must
|
||||
// be created with new root and updated trie database for following usage
|
||||
Commit(collectLeaf bool) (common.Hash, *trie.NodeSet, error)
|
||||
|
||||
// NodeIterator returns an iterator that returns nodes of the trie. Iteration
|
||||
// starts at the key after the given start key.
|
||||
@@ -133,7 +143,7 @@ type cachingDB struct {
|
||||
|
||||
// OpenTrie opens the main account trie at a specific root hash.
|
||||
func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
||||
tr, err := trie.NewSecure(common.Hash{}, root, db.db)
|
||||
tr, err := trie.NewStateTrie(common.Hash{}, root, db.db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -142,7 +152,7 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
||||
|
||||
// OpenStorageTrie opens the storage trie of an account.
|
||||
func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
|
||||
tr, err := trie.NewSecure(addrHash, root, db.db)
|
||||
tr, err := trie.NewStateTrie(addrHash, root, db.db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -152,7 +162,7 @@ func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
|
||||
// CopyTrie returns an independent copy of the given trie.
|
||||
func (db *cachingDB) CopyTrie(t Trie) Trie {
|
||||
switch t := t.(type) {
|
||||
case *trie.SecureTrie:
|
||||
case *trie.StateTrie:
|
||||
return t.Copy()
|
||||
default:
|
||||
panic(fmt.Errorf("unknown trie type %T", t))
|
||||
|
||||
@@ -19,10 +19,10 @@ package state
|
||||
import "github.com/ethereum/go-ethereum/metrics"
|
||||
|
||||
var (
|
||||
accountUpdatedMeter = metrics.NewRegisteredMeter("state/update/account", nil)
|
||||
storageUpdatedMeter = metrics.NewRegisteredMeter("state/update/storage", nil)
|
||||
accountDeletedMeter = metrics.NewRegisteredMeter("state/delete/account", nil)
|
||||
storageDeletedMeter = metrics.NewRegisteredMeter("state/delete/storage", nil)
|
||||
accountCommittedMeter = metrics.NewRegisteredMeter("state/commit/account", nil)
|
||||
storageCommittedMeter = metrics.NewRegisteredMeter("state/commit/storage", nil)
|
||||
accountUpdatedMeter = metrics.NewRegisteredMeter("state/update/account", nil)
|
||||
storageUpdatedMeter = metrics.NewRegisteredMeter("state/update/storage", nil)
|
||||
accountDeletedMeter = metrics.NewRegisteredMeter("state/delete/account", nil)
|
||||
storageDeletedMeter = metrics.NewRegisteredMeter("state/delete/storage", nil)
|
||||
accountTrieCommittedMeter = metrics.NewRegisteredMeter("state/commit/accountnodes", nil)
|
||||
storageTriesCommittedMeter = metrics.NewRegisteredMeter("state/commit/storagenodes", nil)
|
||||
)
|
||||
|
||||
@@ -410,7 +410,7 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error {
|
||||
if genesis == nil {
|
||||
return errors.New("missing genesis block")
|
||||
}
|
||||
t, err := trie.NewSecure(common.Hash{}, genesis.Root(), trie.NewDatabase(db))
|
||||
t, err := trie.NewStateTrie(common.Hash{}, genesis.Root(), trie.NewDatabase(db))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -430,7 +430,7 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error {
|
||||
return err
|
||||
}
|
||||
if acc.Root != emptyRoot {
|
||||
storageTrie, err := trie.NewSecure(common.BytesToHash(accIter.LeafKey()), acc.Root, trie.NewDatabase(db))
|
||||
storageTrie, err := trie.NewStateTrie(common.BytesToHash(accIter.LeafKey()), acc.Root, trie.NewDatabase(db))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -367,7 +367,10 @@ func (dl *diskLayer) generateRange(ctx *generatorContext, owner common.Hash, roo
|
||||
for i, key := range result.keys {
|
||||
snapTrie.Update(key, result.vals[i])
|
||||
}
|
||||
root, _, _ := snapTrie.Commit(nil)
|
||||
root, nodes, _ := snapTrie.Commit(false)
|
||||
if nodes != nil {
|
||||
snapTrieDb.Update(trie.NewWithNodeSet(nodes))
|
||||
}
|
||||
snapTrieDb.Commit(root, false, nil)
|
||||
}
|
||||
// Construct the trie for state iteration, reuse the trie
|
||||
|
||||
@@ -142,17 +142,19 @@ func checkSnapRoot(t *testing.T, snap *diskLayer, trieRoot common.Hash) {
|
||||
type testHelper struct {
|
||||
diskdb ethdb.Database
|
||||
triedb *trie.Database
|
||||
accTrie *trie.SecureTrie
|
||||
accTrie *trie.StateTrie
|
||||
nodes *trie.MergedNodeSet
|
||||
}
|
||||
|
||||
func newHelper() *testHelper {
|
||||
diskdb := rawdb.NewMemoryDatabase()
|
||||
triedb := trie.NewDatabase(diskdb)
|
||||
accTrie, _ := trie.NewSecure(common.Hash{}, common.Hash{}, triedb)
|
||||
accTrie, _ := trie.NewStateTrie(common.Hash{}, common.Hash{}, triedb)
|
||||
return &testHelper{
|
||||
diskdb: diskdb,
|
||||
triedb: triedb,
|
||||
accTrie: accTrie,
|
||||
nodes: trie.NewMergedNodeSet(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,21 +182,26 @@ func (t *testHelper) addSnapStorage(accKey string, keys []string, vals []string)
|
||||
}
|
||||
|
||||
func (t *testHelper) makeStorageTrie(stateRoot, owner common.Hash, keys []string, vals []string, commit bool) []byte {
|
||||
stTrie, _ := trie.NewSecure(owner, common.Hash{}, t.triedb)
|
||||
stTrie, _ := trie.NewStateTrie(owner, common.Hash{}, t.triedb)
|
||||
for i, k := range keys {
|
||||
stTrie.Update([]byte(k), []byte(vals[i]))
|
||||
}
|
||||
var root common.Hash
|
||||
if !commit {
|
||||
root = stTrie.Hash()
|
||||
} else {
|
||||
root, _, _ = stTrie.Commit(nil)
|
||||
return stTrie.Hash().Bytes()
|
||||
}
|
||||
root, nodes, _ := stTrie.Commit(false)
|
||||
if nodes != nil {
|
||||
t.nodes.Merge(nodes)
|
||||
}
|
||||
return root.Bytes()
|
||||
}
|
||||
|
||||
func (t *testHelper) Commit() common.Hash {
|
||||
root, _, _ := t.accTrie.Commit(nil)
|
||||
root, nodes, _ := t.accTrie.Commit(true)
|
||||
if nodes != nil {
|
||||
t.nodes.Merge(nodes)
|
||||
}
|
||||
t.triedb.Update(t.nodes)
|
||||
t.triedb.Commit(root, false, nil)
|
||||
return root
|
||||
}
|
||||
@@ -378,7 +385,7 @@ func TestGenerateCorruptAccountTrie(t *testing.T) {
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
|
||||
|
||||
root, _, _ := helper.accTrie.Commit(nil) // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
|
||||
root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
|
||||
|
||||
// Delete an account trie leaf and ensure the generator chokes
|
||||
helper.triedb.Commit(root, false, nil)
|
||||
@@ -413,18 +420,8 @@ func TestGenerateMissingStorageTrie(t *testing.T) {
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
||||
stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
|
||||
root, _, _ := helper.accTrie.Commit(nil)
|
||||
|
||||
// We can only corrupt the disk database, so flush the tries out
|
||||
helper.triedb.Reference(
|
||||
common.BytesToHash(stRoot),
|
||||
common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"),
|
||||
)
|
||||
helper.triedb.Reference(
|
||||
common.BytesToHash(stRoot),
|
||||
common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"),
|
||||
)
|
||||
helper.triedb.Commit(root, false, nil)
|
||||
root := helper.Commit()
|
||||
|
||||
// Delete a storage trie root and ensure the generator chokes
|
||||
helper.diskdb.Delete(stRoot)
|
||||
@@ -458,18 +455,7 @@ func TestGenerateCorruptStorageTrie(t *testing.T) {
|
||||
stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
|
||||
|
||||
root, _, _ := helper.accTrie.Commit(nil)
|
||||
|
||||
// We can only corrupt the disk database, so flush the tries out
|
||||
helper.triedb.Reference(
|
||||
common.BytesToHash(stRoot),
|
||||
common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"),
|
||||
)
|
||||
helper.triedb.Reference(
|
||||
common.BytesToHash(stRoot),
|
||||
common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"),
|
||||
)
|
||||
helper.triedb.Commit(root, false, nil)
|
||||
root := helper.Commit()
|
||||
|
||||
// Delete a storage trie leaf and ensure the generator chokes
|
||||
helper.diskdb.Delete(common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371").Bytes())
|
||||
@@ -825,10 +811,12 @@ func populateDangling(disk ethdb.KeyValueStore) {
|
||||
// This test will populate some dangling storages to see if they can be cleaned up.
|
||||
func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) {
|
||||
var helper = newHelper()
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
|
||||
helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
|
||||
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
|
||||
|
||||
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
|
||||
@@ -858,10 +846,12 @@ func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) {
|
||||
// This test will populate some dangling storages to see if they can be cleaned up.
|
||||
func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) {
|
||||
var helper = newHelper()
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
|
||||
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
|
||||
|
||||
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()})
|
||||
|
||||
populateDangling(helper.diskdb)
|
||||
|
||||
@@ -319,7 +319,7 @@ func (fi *fastIterator) Slot() []byte {
|
||||
}
|
||||
|
||||
// Release iterates over all the remaining live layer iterators and releases each
|
||||
// of thme individually.
|
||||
// of them individually.
|
||||
func (fi *fastIterator) Release() {
|
||||
for _, it := range fi.iterators {
|
||||
it.it.Release()
|
||||
@@ -327,7 +327,7 @@ func (fi *fastIterator) Release() {
|
||||
fi.iterators = nil
|
||||
}
|
||||
|
||||
// Debug is a convencience helper during testing
|
||||
// Debug is a convenience helper during testing
|
||||
func (fi *fastIterator) Debug() {
|
||||
for _, it := range fi.iterators {
|
||||
fmt.Printf("[p=%v v=%v] ", it.priority, it.it.Hash()[0])
|
||||
|
||||
@@ -265,7 +265,7 @@ func TestPostCapBasicDataAccess(t *testing.T) {
|
||||
snaps.Update(common.HexToHash("0xa3"), common.HexToHash("0xa2"), nil, setAccount("0xa3"), nil)
|
||||
snaps.Update(common.HexToHash("0xb3"), common.HexToHash("0xb2"), nil, setAccount("0xb3"), nil)
|
||||
|
||||
// checkExist verifies if an account exiss in a snapshot
|
||||
// checkExist verifies if an account exists in a snapshot
|
||||
checkExist := func(layer *diffLayer, key string) error {
|
||||
if data, _ := layer.Account(common.HexToHash(key)); data == nil {
|
||||
return fmt.Errorf("expected %x to exist, got nil", common.HexToHash(key))
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
)
|
||||
|
||||
var emptyCodeHash = crypto.Keccak256(nil)
|
||||
@@ -375,23 +376,23 @@ func (s *stateObject) updateRoot(db Database) {
|
||||
|
||||
// CommitTrie the storage trie of the object to db.
|
||||
// This updates the trie root.
|
||||
func (s *stateObject) CommitTrie(db Database) (int, error) {
|
||||
func (s *stateObject) CommitTrie(db Database) (*trie.NodeSet, error) {
|
||||
// If nothing changed, don't bother with hashing anything
|
||||
if s.updateTrie(db) == nil {
|
||||
return 0, nil
|
||||
return nil, nil
|
||||
}
|
||||
if s.dbErr != nil {
|
||||
return 0, s.dbErr
|
||||
return nil, s.dbErr
|
||||
}
|
||||
// Track the amount of time wasted on committing the storage trie
|
||||
if metrics.EnabledExpensive {
|
||||
defer func(start time.Time) { s.db.StorageCommits += time.Since(start) }(time.Now())
|
||||
}
|
||||
root, committed, err := s.trie.Commit(nil)
|
||||
root, nodes, err := s.trie.Commit(false)
|
||||
if err == nil {
|
||||
s.data.Root = root
|
||||
}
|
||||
return committed, err
|
||||
return nodes, err
|
||||
}
|
||||
|
||||
// AddBalance adds amount to s's balance.
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
)
|
||||
|
||||
type stateTest struct {
|
||||
@@ -40,7 +41,7 @@ func newStateTest() *stateTest {
|
||||
|
||||
func TestDump(t *testing.T) {
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
sdb, _ := New(common.Hash{}, NewDatabaseWithConfig(db, nil), nil)
|
||||
sdb, _ := New(common.Hash{}, NewDatabaseWithConfig(db, &trie.Config{Preimages: true}), nil)
|
||||
s := &stateTest{db: db, state: sdb}
|
||||
|
||||
// generate a few entries
|
||||
|
||||
+40
-32
@@ -493,7 +493,7 @@ func (s *StateDB) deleteStateObject(obj *stateObject) {
|
||||
}
|
||||
// Delete the account from the trie
|
||||
addr := obj.Address()
|
||||
if err := s.trie.TryDelete(addr[:]); err != nil {
|
||||
if err := s.trie.TryDeleteAccount(addr[:]); err != nil {
|
||||
s.setError(fmt.Errorf("deleteStateObject (%x) error: %v", addr[:], err))
|
||||
}
|
||||
}
|
||||
@@ -546,20 +546,16 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
|
||||
// If snapshot unavailable or reading from it failed, load from the database
|
||||
if data == nil {
|
||||
start := time.Now()
|
||||
enc, err := s.trie.TryGet(addr.Bytes())
|
||||
var err error
|
||||
data, err = s.trie.TryGetAccount(addr.Bytes())
|
||||
if metrics.EnabledExpensive {
|
||||
s.AccountReads += time.Since(start)
|
||||
}
|
||||
if err != nil {
|
||||
s.setError(fmt.Errorf("getDeleteStateObject (%x) error: %v", addr.Bytes(), err))
|
||||
s.setError(fmt.Errorf("getDeleteStateObject (%x) error: %w", addr.Bytes(), err))
|
||||
return nil
|
||||
}
|
||||
if len(enc) == 0 {
|
||||
return nil
|
||||
}
|
||||
data = new(types.StateAccount)
|
||||
if err := rlp.DecodeBytes(enc, data); err != nil {
|
||||
log.Error("Failed to decode state object", "addr", addr, "err", err)
|
||||
if data == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -783,7 +779,7 @@ func (s *StateDB) GetRefund() uint64 {
|
||||
return s.refund
|
||||
}
|
||||
|
||||
// Finalise finalises the state by removing the s destructed objects and clears
|
||||
// Finalise finalises the state by removing the destructed objects and clears
|
||||
// the journal as well as the refunds. Finalise, however, will not push any updates
|
||||
// into the tries just yet. Only IntermediateRoot or Commit will do that.
|
||||
func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
||||
@@ -805,7 +801,7 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
||||
// If state snapshotting is active, also mark the destruction there.
|
||||
// Note, we can't do this only at the end of a block because multiple
|
||||
// transactions within the same block might self destruct and then
|
||||
// ressurrect an account; but the snapshotter needs both events.
|
||||
// resurrect an account; but the snapshotter needs both events.
|
||||
if s.snap != nil {
|
||||
s.snapDestructs[obj.addrHash] = struct{}{} // We need to maintain account deletions explicitly (will remain set indefinitely)
|
||||
delete(s.snapAccounts, obj.addrHash) // Clear out any previously updated account data (may be recreated via a ressurrect)
|
||||
@@ -853,7 +849,7 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||
// Although naively it makes sense to retrieve the account trie and then do
|
||||
// the contract storage and account updates sequentially, that short circuits
|
||||
// the account prefetcher. Instead, let's process all the storage updates
|
||||
// first, giving the account prefeches just a few more milliseconds of time
|
||||
// first, giving the account prefetches just a few more milliseconds of time
|
||||
// to pull useful data from disk.
|
||||
for addr := range s.stateObjectsPending {
|
||||
if obj := s.stateObjects[addr]; !obj.deleted {
|
||||
@@ -897,7 +893,6 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||
func (s *StateDB) Prepare(thash common.Hash, ti int) {
|
||||
s.thash = thash
|
||||
s.txIndex = ti
|
||||
s.accessList = newAccessList()
|
||||
}
|
||||
|
||||
func (s *StateDB) clearJournalAndRefund() {
|
||||
@@ -905,7 +900,7 @@ func (s *StateDB) clearJournalAndRefund() {
|
||||
s.journal = newJournal()
|
||||
s.refund = 0
|
||||
}
|
||||
s.validRevisions = s.validRevisions[:0] // Snapshots can be created without journal entires
|
||||
s.validRevisions = s.validRevisions[:0] // Snapshots can be created without journal entries
|
||||
}
|
||||
|
||||
// Commit writes the state to the underlying in-memory trie database.
|
||||
@@ -917,23 +912,37 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
s.IntermediateRoot(deleteEmptyObjects)
|
||||
|
||||
// Commit objects to the trie, measuring the elapsed time
|
||||
var storageCommitted int
|
||||
var (
|
||||
accountTrieNodes int
|
||||
storageTrieNodes int
|
||||
nodes = trie.NewMergedNodeSet()
|
||||
)
|
||||
// PluGeth injection
|
||||
codeUpdates := make(map[common.Hash][]byte)
|
||||
// PluGeth injection
|
||||
codeWriter := s.db.TrieDB().DiskDB().NewBatch()
|
||||
for addr := range s.stateObjectsDirty {
|
||||
if obj := s.stateObjects[addr]; !obj.deleted {
|
||||
// Write any contract code associated with the state object
|
||||
if obj.code != nil && obj.dirtyCode {
|
||||
rawdb.WriteCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code)
|
||||
// PluGeth injection
|
||||
codeUpdates[common.BytesToHash(obj.CodeHash())] = obj.code
|
||||
// PluGeth injection
|
||||
obj.dirtyCode = false
|
||||
}
|
||||
// Write any storage changes in the state object to its storage trie
|
||||
committed, err := obj.CommitTrie(s.db)
|
||||
set, err := obj.CommitTrie(s.db)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
storageCommitted += committed
|
||||
// Merge the dirty nodes of storage trie into global set
|
||||
if set != nil {
|
||||
if err := nodes.Merge(set); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
storageTrieNodes += set.Len()
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(s.stateObjectsDirty) > 0 {
|
||||
@@ -944,26 +953,22 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
log.Crit("Failed to commit dirty codes", "error", err)
|
||||
}
|
||||
}
|
||||
// Write the account trie changes, measuing the amount of wasted time
|
||||
// Write the account trie changes, measuring the amount of wasted time
|
||||
var start time.Time
|
||||
if metrics.EnabledExpensive {
|
||||
start = time.Now()
|
||||
}
|
||||
// The onleaf func is called _serially_, so we can reuse the same account
|
||||
// for unmarshalling every time.
|
||||
var account types.StateAccount
|
||||
root, accountCommitted, err := s.trie.Commit(func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash, _ []byte) error {
|
||||
if err := rlp.DecodeBytes(leaf, &account); err != nil {
|
||||
return nil
|
||||
}
|
||||
if account.Root != emptyRoot {
|
||||
s.db.TrieDB().Reference(account.Root, parent)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
root, set, err := s.trie.Commit(true)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
// Merge the dirty nodes of account trie into global set
|
||||
if set != nil {
|
||||
if err := nodes.Merge(set); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
accountTrieNodes = set.Len()
|
||||
}
|
||||
if metrics.EnabledExpensive {
|
||||
s.AccountCommits += time.Since(start)
|
||||
|
||||
@@ -971,8 +976,8 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
storageUpdatedMeter.Mark(int64(s.StorageUpdated))
|
||||
accountDeletedMeter.Mark(int64(s.AccountDeleted))
|
||||
storageDeletedMeter.Mark(int64(s.StorageDeleted))
|
||||
accountCommittedMeter.Mark(int64(accountCommitted))
|
||||
storageCommittedMeter.Mark(int64(storageCommitted))
|
||||
accountTrieCommittedMeter.Mark(int64(accountTrieNodes))
|
||||
storageTriesCommittedMeter.Mark(int64(storageTrieNodes))
|
||||
s.AccountUpdated, s.AccountDeleted = 0, 0
|
||||
s.StorageUpdated, s.StorageDeleted = 0, 0
|
||||
}
|
||||
@@ -1001,6 +1006,9 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
}
|
||||
s.snap, s.snapDestructs, s.snapAccounts, s.snapStorage = nil, nil, nil, nil
|
||||
}
|
||||
if err := s.db.TrieDB().Update(nodes); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
s.originalRoot = root
|
||||
return root, err
|
||||
}
|
||||
|
||||
@@ -771,7 +771,7 @@ func TestStateDBAccessList(t *testing.T) {
|
||||
t.Fatalf("expected %x to be in access list", address)
|
||||
}
|
||||
}
|
||||
// Check that only the expected addresses are present in the acesslist
|
||||
// Check that only the expected addresses are present in the access list
|
||||
for address := range state.accessList.addresses {
|
||||
if _, exist := addressMap[address]; !exist {
|
||||
t.Fatalf("extra address %x in access list", address)
|
||||
|
||||
@@ -305,8 +305,8 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
||||
}
|
||||
for len(nodeElements)+len(codeElements) > 0 {
|
||||
// Sync only half of the scheduled nodes
|
||||
var nodeProcessd int
|
||||
var codeProcessd int
|
||||
var nodeProcessed int
|
||||
var codeProcessed int
|
||||
if len(codeElements) > 0 {
|
||||
codeResults := make([]trie.CodeSyncResult, len(codeElements)/2+1)
|
||||
for i, element := range codeElements[:len(codeResults)] {
|
||||
@@ -321,7 +321,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
||||
t.Fatalf("failed to process result %v", err)
|
||||
}
|
||||
}
|
||||
codeProcessd = len(codeResults)
|
||||
codeProcessed = len(codeResults)
|
||||
}
|
||||
if len(nodeElements) > 0 {
|
||||
nodeResults := make([]trie.NodeSyncResult, len(nodeElements)/2+1)
|
||||
@@ -337,7 +337,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
||||
t.Fatalf("failed to process result %v", err)
|
||||
}
|
||||
}
|
||||
nodeProcessd = len(nodeResults)
|
||||
nodeProcessed = len(nodeResults)
|
||||
}
|
||||
batch := dstDb.NewBatch()
|
||||
if err := sched.Commit(batch); err != nil {
|
||||
@@ -346,7 +346,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
||||
batch.Write()
|
||||
|
||||
paths, nodes, codes = sched.Missing(0)
|
||||
nodeElements = nodeElements[nodeProcessd:]
|
||||
nodeElements = nodeElements[nodeProcessed:]
|
||||
for i := 0; i < len(paths); i++ {
|
||||
nodeElements = append(nodeElements, stateElement{
|
||||
path: paths[i],
|
||||
@@ -354,7 +354,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
||||
syncPath: trie.NewSyncPath([]byte(paths[i])),
|
||||
})
|
||||
}
|
||||
codeElements = codeElements[codeProcessd:]
|
||||
codeElements = codeElements[codeProcessed:]
|
||||
for i := 0; i < len(codes); i++ {
|
||||
codeElements = append(codeElements, stateElement{
|
||||
code: codes[i],
|
||||
|
||||
@@ -212,7 +212,7 @@ type subfetcher struct {
|
||||
|
||||
wake chan struct{} // Wake channel if a new task is scheduled
|
||||
stop chan struct{} // Channel to interrupt processing
|
||||
term chan struct{} // Channel to signal iterruption
|
||||
term chan struct{} // Channel to signal interruption
|
||||
copy chan chan Trie // Channel to request a copy of the current trie
|
||||
|
||||
seen map[string]struct{} // Tracks the entries already loaded
|
||||
@@ -331,7 +331,11 @@ func (sf *subfetcher) loop() {
|
||||
if _, ok := sf.seen[string(task)]; ok {
|
||||
sf.dups++
|
||||
} else {
|
||||
sf.trie.TryGet(task)
|
||||
if len(task) == len(common.Address{}) {
|
||||
sf.trie.TryGetAccount(task)
|
||||
} else {
|
||||
sf.trie.TryGet(task)
|
||||
}
|
||||
sf.seen[string(task)] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||
statedb.Prepare(tx.Hash(), i)
|
||||
pluginPreProcessTransaction(tx, block, i)
|
||||
blockTracer.PreProcessTransaction(tx, block, i)
|
||||
receipt, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv)
|
||||
receipt, err := applyTransaction(msg, p.config, nil, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv)
|
||||
if err != nil {
|
||||
pluginBlockProcessingError(tx, block, err)
|
||||
blockTracer.BlockProcessingError(tx, block, err)
|
||||
@@ -110,7 +110,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||
return receipts, allLogs, *usedGas, nil
|
||||
}
|
||||
|
||||
func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) {
|
||||
func applyTransaction(msg types.Message, config *params.ChainConfig, author *common.Address, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) {
|
||||
// Create a new context to be used in the EVM environment.
|
||||
txContext := NewEVMTxContext(msg)
|
||||
evm.Reset(txContext, statedb)
|
||||
@@ -167,5 +167,5 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
|
||||
// Create a new context to be used in the EVM environment
|
||||
blockContext := NewEVMBlockContext(header, bc, author)
|
||||
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg)
|
||||
return applyTransaction(msg, config, bc, author, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv)
|
||||
return applyTransaction(msg, config, author, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv)
|
||||
}
|
||||
|
||||
+5
-4
@@ -19,6 +19,7 @@ package core
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@@ -57,12 +58,12 @@ func newTxJournal(path string) *txJournal {
|
||||
// load parses a transaction journal dump from disk, loading its contents into
|
||||
// the specified pool.
|
||||
func (journal *txJournal) load(add func([]*types.Transaction) []error) error {
|
||||
// Skip the parsing if the journal file doesn't exist at all
|
||||
if !common.FileExist(journal.path) {
|
||||
return nil
|
||||
}
|
||||
// Open the journal for loading any past transactions
|
||||
input, err := os.Open(journal.path)
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
// Skip the parsing if the journal file doesn't exist at all
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+1
-1
@@ -317,7 +317,7 @@ func (b *Block) Header() *Header { return CopyHeader(b.header) }
|
||||
func (b *Block) Body() *Body { return &Body{b.transactions, b.uncles} }
|
||||
|
||||
// Size returns the true RLP encoded storage size of the block, either by encoding
|
||||
// and returning it, or returning a previsouly cached value.
|
||||
// and returning it, or returning a previously cached value.
|
||||
func (b *Block) Size() common.StorageSize {
|
||||
if size := b.size.Load(); size != nil {
|
||||
return size.(common.StorageSize)
|
||||
|
||||
@@ -314,7 +314,7 @@ func TestRlpDecodeParentHash(t *testing.T) {
|
||||
}
|
||||
// Also test a very very large header.
|
||||
{
|
||||
// The rlp-encoding of the heder belowCauses _total_ length of 65540,
|
||||
// The rlp-encoding of the header belowCauses _total_ length of 65540,
|
||||
// which is the first to blow the fast-path.
|
||||
h := &Header{
|
||||
ParentHash: want,
|
||||
|
||||
@@ -154,7 +154,7 @@ func bloomValues(data []byte, hashbuf []byte) (uint, byte, uint, byte, uint, byt
|
||||
return i1, v1, i2, v2, i3, v3
|
||||
}
|
||||
|
||||
// BloomLookup is a convenience-method to check presence int he bloom filter
|
||||
// BloomLookup is a convenience-method to check presence in the bloom filter
|
||||
func BloomLookup(bin Bloom, topic bytesBacked) bool {
|
||||
return bin.Test(topic.Bytes())
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode
|
||||
cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
cfg.GasLimit = gas
|
||||
if len(tracerCode) > 0 {
|
||||
tracer, err := tracers.New(tracerCode, new(tracers.Context))
|
||||
tracer, err := tracers.New(tracerCode, new(tracers.Context), nil)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
@@ -457,7 +457,7 @@ func BenchmarkSimpleLoop(b *testing.B) {
|
||||
byte(vm.JUMP),
|
||||
}
|
||||
|
||||
calllRevertingContractWithInput := []byte{
|
||||
callRevertingContractWithInput := []byte{
|
||||
byte(vm.JUMPDEST), //
|
||||
// push args for the call
|
||||
byte(vm.PUSH1), 0, // out size
|
||||
@@ -485,7 +485,7 @@ func BenchmarkSimpleLoop(b *testing.B) {
|
||||
benchmarkNonModifyingCode(100000000, loopingCode, "loop-100M", "", b)
|
||||
benchmarkNonModifyingCode(100000000, callInexistant, "call-nonexist-100M", "", b)
|
||||
benchmarkNonModifyingCode(100000000, callEOA, "call-EOA-100M", "", b)
|
||||
benchmarkNonModifyingCode(100000000, calllRevertingContractWithInput, "call-reverting-100M", "", b)
|
||||
benchmarkNonModifyingCode(100000000, callRevertingContractWithInput, "call-reverting-100M", "", b)
|
||||
|
||||
//benchmarkNonModifyingCode(10000000, staticCallIdentity, "staticcall-identity-10M", b)
|
||||
//benchmarkNonModifyingCode(10000000, loopingCode, "loop-10M", b)
|
||||
@@ -832,7 +832,7 @@ func TestRuntimeJSTracer(t *testing.T) {
|
||||
statedb.SetCode(common.HexToAddress("0xee"), calleeCode)
|
||||
statedb.SetCode(common.HexToAddress("0xff"), depressedCode)
|
||||
|
||||
tracer, err := tracers.New(jsTracer, new(tracers.Context))
|
||||
tracer, err := tracers.New(jsTracer, new(tracers.Context), nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -868,7 +868,7 @@ func TestJSTracerCreateTx(t *testing.T) {
|
||||
code := []byte{byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN)}
|
||||
|
||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
tracer, err := tracers.New(jsTracer, new(tracers.Context))
|
||||
tracer, err := tracers.New(jsTracer, new(tracers.Context), nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user