Skip to content

Commit

Permalink
feat: add proof keeper (#90)
Browse files Browse the repository at this point in the history
Co-authored-by: will@2012 <[email protected]>
  • Loading branch information
will-2012 and will@2012 authored May 21, 2024
1 parent 52661bd commit e916a8a
Show file tree
Hide file tree
Showing 26 changed files with 1,293 additions and 74 deletions.
2 changes: 2 additions & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ var (
utils.StateHistoryFlag,
utils.ProposeBlockIntervalFlag,
utils.PathDBNodeBufferTypeFlag,
utils.EnableProofKeeperFlag,
utils.KeepProofBlockSpanFlag,
utils.LightServeFlag, // deprecated
utils.LightIngressFlag, // deprecated
utils.LightEgressFlag, // deprecated
Expand Down
21 changes: 19 additions & 2 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,11 @@ import (
"strings"
"time"

"github.com/ethereum/go-ethereum/core/opcodeCompiler/compiler"
pcsclite "github.com/gballet/go-libpcsclite"
gopsutil "github.com/shirou/gopsutil/mem"
"github.com/urfave/cli/v2"

"github.com/ethereum/go-ethereum/core/opcodeCompiler/compiler"

"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -329,6 +328,18 @@ var (
Value: pathdb.DefaultProposeBlockInterval,
Category: flags.StateCategory,
}
EnableProofKeeperFlag = &cli.BoolFlag{
Name: "pathdb.enableproofkeeper",
Usage: "Enable path db proof keeper to store proposed proof",
Value: false,
Category: flags.StateCategory,
}
KeepProofBlockSpanFlag = &cli.Uint64Flag{
Name: "pathdb.keepproofblockspan",
Usage: "Block span of keep proof (default = 90,000 blocks)",
Value: params.FullImmutabilityThreshold,
Category: flags.StateCategory,
}
StateHistoryFlag = &cli.Uint64Flag{
Name: "history.state",
Usage: "Number of recent blocks to retain state history for (default = 90,000 blocks, 0 = entire chain)",
Expand Down Expand Up @@ -1861,6 +1872,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.IsSet(ProposeBlockIntervalFlag.Name) {
cfg.ProposeBlockInterval = ctx.Uint64(ProposeBlockIntervalFlag.Name)
}
if ctx.IsSet(EnableProofKeeperFlag.Name) {
cfg.EnableProofKeeper = ctx.Bool(EnableProofKeeperFlag.Name)
}
if ctx.IsSet(KeepProofBlockSpanFlag.Name) {
cfg.KeepProofBlockSpan = ctx.Uint64(KeepProofBlockSpanFlag.Name)
}
if ctx.String(GCModeFlag.Name) == "archive" && cfg.TransactionHistory != 0 {
cfg.TransactionHistory = 0
log.Warn("Disabled transaction unindexing for archive node")
Expand Down
33 changes: 33 additions & 0 deletions common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -475,3 +475,36 @@ func (d *Decimal) UnmarshalJSON(input []byte) error {
return err
}
}

// ProofList implements ethdb.KeyValueWriter and collects the proofs as
// hex-strings for delivery to rpc-caller.
type ProofList []string

// Put implements ethdb.KeyValueWriter put interface.
func (n *ProofList) Put(key []byte, value []byte) error {
*n = append(*n, hexutil.Encode(value))
return nil
}

// Delete implements ethdb.KeyValueWriter delete interface.
func (n *ProofList) Delete(key []byte) error {
panic("not supported")
}

// AccountResult is the result of a GetProof operation.
type AccountResult struct {
Address Address `json:"address"`
AccountProof []string `json:"accountProof"`
Balance *big.Int `json:"balance"`
CodeHash Hash `json:"codeHash"`
Nonce uint64 `json:"nonce"`
StorageHash Hash `json:"storageHash"`
StorageProof []StorageResult `json:"storageProof"`
}

// StorageResult provides a proof for a key-value pair.
type StorageResult struct {
Key string `json:"key"`
Value *big.Int `json:"value"`
Proof []string `json:"proof"`
}
27 changes: 23 additions & 4 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,16 @@ type CacheConfig struct {
StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top
PathNodeBuffer pathdb.NodeBufferType // Type of trienodebuffer to cache trie nodes in disklayer
ProposeBlockInterval uint64 // Propose block to L1 block interval.
EnableProofKeeper bool // Whether to enable proof keeper
KeepProofBlockSpan uint64 // Block span of keep proof
SnapshotNoBuild bool // Whether the background generation is allowed
SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it

TrieCommitInterval uint64 // Define a block height interval, commit trie every TrieCommitInterval block height.
}

// triedbConfig derives the configures for trie database.
func (c *CacheConfig) triedbConfig() *trie.Config {
func (c *CacheConfig) triedbConfig(keepFunc pathdb.NotifyKeepFunc) *trie.Config {
config := &trie.Config{
Preimages: c.Preimages,
NoTries: c.NoTries,
Expand All @@ -182,6 +184,7 @@ func (c *CacheConfig) triedbConfig() *trie.Config {
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
DirtyCacheSize: c.TrieDirtyLimit * 1024 * 1024,
ProposeBlockInterval: c.ProposeBlockInterval,
NotifyKeep: keepFunc,
}
}
return config
Expand Down Expand Up @@ -232,6 +235,7 @@ type BlockChain struct {
flushInterval atomic.Int64 // Time interval (processing time) after which to flush a state
triedb *trie.Database // The database handler for maintaining trie nodes.
stateCache state.Database // State database to reuse between imports (contains state cache)
proofKeeper *ProofKeeper // Store/Query op-proposal proof to ensure consistent.

// txLookupLimit is the maximum number of blocks from head whose tx indices
// are reserved:
Expand Down Expand Up @@ -292,8 +296,16 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
if cacheConfig == nil {
cacheConfig = defaultCacheConfig
}
opts := &proofKeeperOptions{
enable: cacheConfig.EnableProofKeeper,
keepProofBlockSpan: cacheConfig.KeepProofBlockSpan,
watchStartKeepCh: make(chan *pathdb.KeepRecord),
notifyFinishKeepCh: make(chan error),
}
proofKeeper := newProofKeeper(opts)
// Open trie database with provided config
triedb := trie.NewDatabase(db, cacheConfig.triedbConfig())
trieConfig := cacheConfig.triedbConfig(proofKeeper.GetNotifyKeepRecordFunc())
triedb := trie.NewDatabase(db, trieConfig)

// Setup the genesis block, commit the provided genesis specification
// to database if the genesis block is not present yet, or load the
Expand Down Expand Up @@ -341,7 +353,12 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
bc.prefetcher = newStatePrefetcher(chainConfig, bc, engine)
bc.processor = NewStateProcessor(chainConfig, bc, engine)

var err error
err := proofKeeper.Start(bc, db)
if err != nil {
return nil, err
}
bc.proofKeeper = proofKeeper

bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.insertStopped)
if err != nil {
return nil, err
Expand Down Expand Up @@ -1037,6 +1054,9 @@ func (bc *BlockChain) Stop() {
if err := bc.triedb.Journal(bc.CurrentBlock().Root); err != nil {
log.Info("Failed to journal in-memory trie nodes", "err", err)
}
if err := bc.proofKeeper.Stop(); err != nil {
log.Info("Failed to stop proof keeper", "err", err)
}
} else {
// Ensure the state of a recent block is also stored to disk before exiting.
// We're writing three different states to catch different restart scenarios:
Expand All @@ -1057,7 +1077,6 @@ func (bc *BlockChain) Stop() {
for _, offset := range blockOffsets {
if number := bc.CurrentBlock().Number.Uint64(); number > offset {
recent := bc.GetBlockByNumber(number - offset)

log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root())
if err := triedb.Commit(recent.Root(), true); err != nil {
log.Error("Failed to commit recent state trie", "err", err)
Expand Down
3 changes: 3 additions & 0 deletions core/blockchain_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,3 +442,6 @@ func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscript
func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscription {
return bc.scope.Track(bc.blockProcFeed.Subscribe(ch))
}

// ProofKeeper returns block chain proof keeper.
func (bc *BlockChain) ProofKeeper() *ProofKeeper { return bc.proofKeeper }
Loading

0 comments on commit e916a8a

Please sign in to comment.