Skip to content

Commit eb7e309

Browse files
unclezorozjubfd
and
zjubfd
authored
[R4R] implement State Verification && Snapshot Commit pipeline (#668)
* pipeline commit trie add metrics reopen trie * add unit testcase * resolve keefe's comment * resolve igor's comments * update prefetch remove prefetcher * no need to return error for precacheTransaction * fix lint issue * add some comments * remove useless code * add default option is false * fix diffsync nil point * fix panic on GetProofByHash Co-authored-by: zjubfd <zjubfd@google.com>
1 parent 476d520 commit eb7e309

40 files changed

+882
-396
lines changed

cmd/evm/internal/t8ntool/execution.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
223223
statedb.AddBalance(pre.Env.Coinbase, minerReward)
224224
}
225225
// Commit block
226-
root, _, err := statedb.Commit(chainConfig.IsEIP158(vmContext.BlockNumber))
226+
statedb.Finalise(chainConfig.IsEIP158(vmContext.BlockNumber))
227+
statedb.AccountsIntermediateRoot()
228+
root, _, err := statedb.Commit(nil)
227229
if err != nil {
228230
fmt.Fprintf(os.Stderr, "Could not commit state: %v", err)
229231
return nil, nil, NewError(ErrorEVM, fmt.Errorf("could not commit state: %v", err))
@@ -252,7 +254,9 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB
252254
}
253255
}
254256
// Commit and re-open to start with a clean state.
255-
root, _, _ := statedb.Commit(false)
257+
statedb.Finalise(false)
258+
statedb.AccountsIntermediateRoot()
259+
root, _, _ := statedb.Commit(nil)
256260
statedb, _ = state.New(root, sdb, nil)
257261
return statedb
258262
}

cmd/evm/runner.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,9 @@ func runCmd(ctx *cli.Context) error {
268268
output, leftOverGas, stats, err := timedExec(bench, execFunc)
269269

270270
if ctx.GlobalBool(DumpFlag.Name) {
271-
statedb.Commit(true)
271+
statedb.Finalise(true)
272+
statedb.AccountsIntermediateRoot()
273+
statedb.Commit(nil)
272274
statedb.IntermediateRoot(true)
273275
fmt.Println(string(statedb.Dump(false, false, true)))
274276
}

cmd/evm/staterunner.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ func stateTestCmd(ctx *cli.Context) error {
101101
_, state, err := test.Run(st, cfg, false)
102102
// print state root for evmlab tracing
103103
if ctx.GlobalBool(MachineFlag.Name) && state != nil {
104-
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%x\"}\n", state.IntermediateRoot(false))
104+
root := state.IntermediateRoot(false)
105+
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%x\"}\n", root)
105106
}
106107
if err != nil {
107108
// Test failed, mark as so and dump any state to aid debugging

cmd/geth/main.go

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ var (
7272
utils.DirectBroadcastFlag,
7373
utils.DisableSnapProtocolFlag,
7474
utils.DiffSyncFlag,
75+
utils.PipeCommitFlag,
7576
utils.RangeLimitFlag,
7677
utils.USBFlag,
7778
utils.SmartCardDaemonPathFlag,

cmd/utils/flags.go

+7
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ var (
127127
Usage: "Enable diffy sync, Please note that enable diffsync will improve the syncing speed, " +
128128
"but will degrade the security to light client level",
129129
}
130+
PipeCommitFlag = cli.BoolFlag{
131+
Name: "pipecommit",
132+
Usage: "Enable MPT pipeline commit, it will improve syncing performance. It is an experimental feature(default is false)",
133+
}
130134
RangeLimitFlag = cli.BoolFlag{
131135
Name: "rangelimit",
132136
Usage: "Enable 5000 blocks limit for range query",
@@ -1632,6 +1636,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
16321636
if ctx.GlobalIsSet(DiffSyncFlag.Name) {
16331637
cfg.DiffSync = ctx.GlobalBool(DiffSyncFlag.Name)
16341638
}
1639+
if ctx.GlobalIsSet(PipeCommitFlag.Name) {
1640+
cfg.PipeCommit = ctx.GlobalBool(PipeCommitFlag.Name)
1641+
}
16351642
if ctx.GlobalIsSet(RangeLimitFlag.Name) {
16361643
cfg.RangeLimit = ctx.GlobalBool(RangeLimitFlag.Name)
16371644
}

consensus/clique/clique.go

+4
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,11 @@ func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
560560
func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB,
561561
txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) {
562562
// No block rewards in PoA, so the state remains as is and uncles are dropped
563+
var err error
563564
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
565+
if err != nil {
566+
return nil, nil, err
567+
}
564568
header.UncleHash = types.CalcUncleHash(nil)
565569

566570
// Assemble and return the final block for sealing

core/block_validator.go

+22-7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package core
1818

1919
import (
2020
"fmt"
21+
"time"
2122

2223
"github.com/ethereum/go-ethereum/consensus"
2324
"github.com/ethereum/go-ethereum/core/state"
@@ -26,6 +27,8 @@ import (
2627
"github.com/ethereum/go-ethereum/trie"
2728
)
2829

30+
const badBlockCacheExpire = 30 * time.Second
31+
2932
// BlockValidator is responsible for validating block headers, uncles and
3033
// processed state.
3134
//
@@ -54,6 +57,9 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
5457
if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) {
5558
return ErrKnownBlock
5659
}
60+
if v.bc.isCachedBadBlock(block) {
61+
return ErrKnownBadBlock
62+
}
5763
// Header validity is known at this point, check the uncles and transactions
5864
header := block.Header()
5965
if err := v.engine.VerifyUncles(v.bc, block); err != nil {
@@ -106,7 +112,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
106112
// transition, such as amount of used gas, the receipt roots and the state root
107113
// itself. ValidateState returns a database batch if the validation was a success
108114
// otherwise nil and an error is returned.
109-
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error {
115+
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64, skipHeavyVerify bool) error {
110116
header := block.Header()
111117
if block.GasUsed() != usedGas {
112118
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
@@ -125,17 +131,26 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
125131
receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil))
126132
if receiptSha != header.ReceiptHash {
127133
return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha)
128-
} else {
129-
return nil
130134
}
135+
return nil
131136
},
132-
func() error {
137+
}
138+
if skipHeavyVerify {
139+
validateFuns = append(validateFuns, func() error {
140+
if err := statedb.WaitPipeVerification(); err != nil {
141+
return err
142+
}
143+
statedb.Finalise(v.config.IsEIP158(header.Number))
144+
statedb.AccountsIntermediateRoot()
145+
return nil
146+
})
147+
} else {
148+
validateFuns = append(validateFuns, func() error {
133149
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
134150
return fmt.Errorf("invalid merkle root (remote: %x local: %x)", header.Root, root)
135-
} else {
136-
return nil
137151
}
138-
},
152+
return nil
153+
})
139154
}
140155
validateRes := make(chan error, len(validateFuns))
141156
for _, f := range validateFuns {

0 commit comments

Comments
 (0)