Skip to content

Commit be53153

Browse files
committed
rewind to last non verified block when restart fast node
1 parent b3a701d commit be53153

File tree

3 files changed

+19
-185
lines changed

3 files changed

+19
-185
lines changed

core/blockchain.go

-61
Original file line numberDiff line numberDiff line change
@@ -3236,67 +3236,6 @@ func (bc *BlockChain) GetTrustedDiffLayer(blockHash common.Hash) *types.DiffLaye
32363236
return diff
32373237
}
32383238

3239-
// GenerateDiffLayer generates DiffLayer of a specified block by replaying the block's transactions.
3240-
// If the block is an empty block, no DiffLayer will be generated.
3241-
// The generated DiffLayer whose Receipts are empty, whose DiffAccounts' storage root is empty.
3242-
func (bc *BlockChain) GenerateDiffLayer(blockHash common.Hash) (*types.DiffLayer, error) {
3243-
if bc.snaps == nil {
3244-
return nil, fmt.Errorf("snapshot disabled, can't generate difflayer")
3245-
}
3246-
3247-
block := bc.GetBlockByHash(blockHash)
3248-
if block == nil {
3249-
return nil, fmt.Errorf("block not found, block number: %d, blockhash: %v", block.NumberU64(), blockHash)
3250-
}
3251-
3252-
parent := bc.GetBlockByHash(block.ParentHash())
3253-
if parent == nil {
3254-
return nil, fmt.Errorf("block not found, block number: %d, blockhash: %v", block.NumberU64()-1, block.ParentHash())
3255-
}
3256-
statedb, err := bc.StateAt(parent.Root())
3257-
if err != nil {
3258-
return nil, fmt.Errorf("state not found for block number (%d): %v", parent.NumberU64(), err)
3259-
}
3260-
3261-
// Empty block, no DiffLayer would be generated.
3262-
if block.Header().TxHash == types.EmptyRootHash {
3263-
return nil, nil
3264-
}
3265-
3266-
// Replay transactions.
3267-
signer := types.MakeSigner(bc.Config(), block.Number())
3268-
for _, tx := range block.Transactions() {
3269-
msg, _ := tx.AsMessage(signer)
3270-
txContext := NewEVMTxContext(msg)
3271-
context := NewEVMBlockContext(block.Header(), bc, nil)
3272-
vmenv := vm.NewEVM(context, txContext, statedb, bc.Config(), vm.Config{})
3273-
3274-
if posa, ok := bc.Engine().(consensus.PoSA); ok {
3275-
if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
3276-
balance := statedb.GetBalance(consensus.SystemAddress)
3277-
if balance.Cmp(common.Big0) > 0 {
3278-
statedb.SetBalance(consensus.SystemAddress, big.NewInt(0))
3279-
statedb.AddBalance(block.Header().Coinbase, balance)
3280-
}
3281-
}
3282-
}
3283-
3284-
if _, err := ApplyMessage(vmenv, msg, new(GasPool).AddGas(tx.Gas())); err != nil {
3285-
return nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
3286-
}
3287-
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
3288-
}
3289-
3290-
diffLayer := statedb.GenerateDiffLayer()
3291-
if diffLayer != nil {
3292-
diffLayer.BlockHash = blockHash
3293-
diffLayer.Number = block.NumberU64()
3294-
bc.cacheDiffLayer(diffLayer, true)
3295-
}
3296-
3297-
return diffLayer, nil
3298-
}
3299-
33003239
func CalculateDiffHash(d *types.DiffLayer) (common.Hash, error) {
33013240
if d == nil {
33023241
return common.Hash{}, fmt.Errorf("nil diff layer")

core/blockchain_diff_test.go

-117
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ import (
2727
"testing"
2828
"time"
2929

30-
"github.com/ethereum/go-ethereum/consensus/clique"
31-
3230
"golang.org/x/crypto/sha3"
3331

3432
"github.com/ethereum/go-ethereum/common"
@@ -647,118 +645,3 @@ func TestGetRootByDiffHash(t *testing.T) {
647645
testGetRootByDiffHash(t, chain1, chain2, 24, types.StatusBlockNewer)
648646
testGetRootByDiffHash(t, chain1, chain2, 35, types.StatusBlockTooNew)
649647
}
650-
651-
func newBlockChainWithCliqueEngine(blocks int) *BlockChain {
652-
signer := types.HomesteadSigner{}
653-
db := rawdb.NewMemoryDatabase()
654-
engine := clique.New(params.AllCliqueProtocolChanges.Clique, db)
655-
genspec := &Genesis{
656-
//Config: params.TestChainConfig,
657-
ExtraData: make([]byte, 32+common.AddressLength+65),
658-
Alloc: GenesisAlloc{testAddr: {Balance: big.NewInt(100000000000000000)}},
659-
}
660-
copy(genspec.ExtraData[32:], testAddr[:])
661-
genesis := genspec.MustCommit(db)
662-
663-
chain, _ := NewBlockChain(db, nil, params.AllCliqueProtocolChanges, engine, vm.Config{}, nil, nil, EnableBlockValidator(params.AllCliqueProtocolChanges, engine, 0 /*LocalVerify*/, nil))
664-
generator := func(i int, block *BlockGen) {
665-
// The chain maker doesn't have access to a chain, so the difficulty will be
666-
// lets unset (nil). Set it here to the correct value.
667-
// block.SetCoinbase(testAddr)
668-
block.SetDifficulty(big.NewInt(2))
669-
670-
for idx, testBlock := range testBlocks {
671-
// Specific block setting, the index in this generator has 1 diff from specified blockNr.
672-
if i+1 == testBlock.blockNr {
673-
for _, testTransaction := range testBlock.txs {
674-
var transaction *types.Transaction
675-
if testTransaction.to == nil {
676-
transaction = types.NewContractCreation(block.TxNonce(testAddr),
677-
testTransaction.value, uint64(commonGas), nil, testTransaction.data)
678-
} else {
679-
transaction = types.NewTransaction(block.TxNonce(testAddr), *testTransaction.to,
680-
testTransaction.value, uint64(commonGas), nil, testTransaction.data)
681-
}
682-
tx, err := types.SignTx(transaction, signer, testKey)
683-
if err != nil {
684-
panic(err)
685-
}
686-
block.AddTxWithChain(chain, tx)
687-
}
688-
break
689-
}
690-
691-
// Default block setting.
692-
if idx == len(testBlocks)-1 {
693-
// We want to simulate an empty middle block, having the same state as the
694-
// first one. The last is needs a state change again to force a reorg.
695-
for _, testTransaction := range testBlocks[0].txs {
696-
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), *testTransaction.to,
697-
testTransaction.value, uint64(commonGas), nil, testTransaction.data), signer, testKey)
698-
if err != nil {
699-
panic(err)
700-
}
701-
block.AddTxWithChain(chain, tx)
702-
}
703-
}
704-
}
705-
706-
}
707-
bs, _ := GenerateChain(params.AllCliqueProtocolChanges, genesis, engine, db, blocks, generator)
708-
for i, block := range bs {
709-
header := block.Header()
710-
if i > 0 {
711-
header.ParentHash = bs[i-1].Hash()
712-
}
713-
header.Extra = make([]byte, 32+65)
714-
header.Difficulty = big.NewInt(2)
715-
716-
sig, _ := crypto.Sign(clique.SealHash(header).Bytes(), testKey)
717-
copy(header.Extra[len(header.Extra)-65:], sig)
718-
bs[i] = block.WithSeal(header)
719-
}
720-
721-
if _, err := chain.InsertChain(bs); err != nil {
722-
panic(err)
723-
}
724-
725-
return chain
726-
}
727-
728-
func TestGenerateDiffLayer(t *testing.T) {
729-
blockNum := 32
730-
chain := newBlockChainWithCliqueEngine(blockNum)
731-
defer chain.Stop()
732-
733-
for blockNr := 1; blockNr <= blockNum; blockNr++ {
734-
block := chain.GetBlockByNumber(uint64(blockNr))
735-
if block == nil {
736-
t.Fatal("block should not be nil")
737-
}
738-
739-
expDiffLayer := chain.GetTrustedDiffLayer(block.Hash())
740-
if expDiffLayer == nil {
741-
// Skip empty block.
742-
if blockNr == 15 {
743-
continue
744-
}
745-
t.Fatalf("unexpected nil diff layer, block number: %v, block hash: %v", blockNr, block.Hash())
746-
}
747-
expDiffHash, err := CalculateDiffHash(expDiffLayer)
748-
if err != nil {
749-
t.Fatalf("compute diff hash failed: %v", err)
750-
}
751-
752-
diffLayer, err := chain.GenerateDiffLayer(block.Hash())
753-
if err != nil || diffLayer == nil {
754-
t.Fatalf("generate diff layer failed: %v", err)
755-
}
756-
diffHash, err := CalculateDiffHash(diffLayer)
757-
if err != nil {
758-
t.Fatalf("compute diff hash failed: %v", err)
759-
}
760-
if expDiffHash != diffHash {
761-
t.Fatalf("generated wrong diff layer for block: %d, expected hash: %v, real hash: %v", blockNr, expDiffHash, diffHash)
762-
}
763-
}
764-
}

core/remote_state_verifier.go

+19-7
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,26 @@ func NewVerifyManager(blockchain *BlockChain, peers verifyPeers, allowInsecure b
7171
if oldBlock == nil {
7272
return nil, fmt.Errorf("block is nil, number: %d", number)
7373
}
74-
blockHash := oldBlock.Hash()
75-
_, err := blockchain.GenerateDiffLayer(blockHash)
76-
if err != nil {
77-
return nil, err
74+
75+
// rewind to last non verified block
76+
blockchain.SetHead(oldBlock.NumberU64())
77+
block = oldBlock
78+
break
79+
}
80+
81+
number = block.Number()
82+
for i := maxForkHeight; i >= 0; i-- {
83+
if new(big.Int).Sub(number, big.NewInt(int64(i))).Cmp(common.Big0) <= 0 {
84+
continue
85+
}
86+
oldBlock := blockchain.GetBlockByNumber(number.Uint64() - uint64(i))
87+
if oldBlock == nil {
88+
return nil, fmt.Errorf("block is nil, number: %d", number)
7889
}
79-
diffLayerCh := make(chan struct{})
80-
close(diffLayerCh)
81-
blockchain.diffLayerChanCache.Store(blockHash, diffLayerCh)
90+
// When inserting a block,
91+
// the block before 11 blocks will be verified,
92+
// so the parent block of 11-22 will directly write the verification information.
93+
verifiedCache.Add(oldBlock.Hash(), true)
8294
}
8395

8496
vm := &remoteVerifyManager{

0 commit comments

Comments
 (0)