Skip to content

Commit

Permalink
fix: make keeper querier work
Browse files Browse the repository at this point in the history
  • Loading branch information
will@2012 committed Apr 18, 2024
1 parent 0e170c5 commit e6c20fa
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 41 deletions.
1 change: 0 additions & 1 deletion core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
if cacheConfig.StateScheme == rawdb.PathScheme && trieConfig.PathDB.TrieNodeBufferType == pathdb.NodeBufferList {
opts := &proofKeeperOptions{
enable: true,
keepInterval: trieConfig.PathDB.ProposeBlockInterval,
watchStartKeepCh: trieConfig.PathDB.KeepCh,
notifyFinishKeepCh: trieConfig.PathDB.WaitKeepCh,
rpcClient: cacheConfig.RpcClient,
Expand Down
79 changes: 53 additions & 26 deletions core/proof_keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"math/big"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
Expand All @@ -27,28 +28,29 @@ var (
// keeperMetaRecord is used to ensure proof continuous in scenarios such as enable/disable keeper, interval changes, reorg, etc.
// which is stored in kv db.
type keeperMetaRecord struct {
blockID uint64
proofID uint64
proposedInterval uint64
blockID uint64 `json:"blockID"`
proofID uint64 `json:"proofID"`
keepInterval uint64 `json:"keepInterval"`
}

// proofDataRecord is used to store proposed proof data.
// which is stored in ancient db.
type proofDataRecord struct {
ProofID uint64 `json:"proofID"`
BlockID uint64 `json:"blockID"`
StateRoot common.Hash `json:"stateRoot"`
Address common.Address `json:"address"`
AccountProof []string `json:"accountProof"`
Balance *big.Int `json:"balance"`
CodeHash common.Hash `json:"codeHash"`
Nonce uint64 `json:"nonce"`
StorageHash common.Hash `json:"storageHash"`
ProofID uint64 `json:"proofID"`
BlockID uint64 `json:"blockID"`
StateRoot common.Hash `json:"stateRoot"`

Address common.Address `json:"address"`
AccountProof []string `json:"accountProof"`
Balance *big.Int `json:"balance"`
CodeHash common.Hash `json:"codeHash"`
Nonce uint64 `json:"nonce"`
StorageHash common.Hash `json:"storageHash"`
StorageProof []common.StorageResult `json:"storageProof"`
}

type proofKeeperOptions struct {
enable bool
keepInterval uint64
watchStartKeepCh chan *pathdb.KeepRecord
notifyFinishKeepCh chan struct{}
rpcClient *rpc.Client
Expand Down Expand Up @@ -114,6 +116,7 @@ func (keeper *ProofKeeper) getInnerProof(kRecord *pathdb.KeepRecord) (*proofData
CodeHash: rawPoof.CodeHash,
Nonce: rawPoof.Nonce,
StorageHash: rawPoof.StorageHash,
StorageProof: rawPoof.StorageProof,
}
log.Info("Succeed to get proof", "proof_record", pRecord)
return pRecord, nil
Expand All @@ -127,11 +130,13 @@ func (keeper *ProofKeeper) eventLoop() {
for {
select {
case keepRecord := <-keeper.opts.watchStartKeepCh:
log.Info("keep proof", "record", keepRecord)
// log.Info("keep proof", "record", keepRecord)
var (
hasTruncatedMeta bool
curProofID uint64
startTimestamp time.Time
)
startTimestamp = time.Now()
hasTruncatedMeta = keeper.truncateKeeperMetaRecordHeadIfNeeded(keepRecord.BlockID)
metaList := keeper.getKeeperMetaRecordList()
if len(metaList) == 0 {
Expand All @@ -152,14 +157,18 @@ func (keeper *ProofKeeper) eventLoop() {
if hasTruncatedMeta || !putKeeperMetaRecordOnce {
putKeeperMetaRecordOnce = true
keeper.putKeeperMetaRecord(&keeperMetaRecord{
proposedInterval: keeper.opts.keepInterval,
blockID: keepRecord.BlockID,
proofID: curProofID,
blockID: keepRecord.BlockID,
proofID: curProofID,
keepInterval: keepRecord.KeepInterval,
})
}
proofRecord.ProofID = curProofID
keeper.putProofDataRecord(proofRecord)
}
log.Info("Keep a new proof",
"block_id", keepRecord.BlockID,
"state_root", keepRecord.StateRoot.String(),
"error", err, "elapsed", common.PrettyDuration(time.Since(startTimestamp)))
keeper.opts.notifyFinishKeepCh <- struct{}{}
case queryBlockID := <-keeper.queryProofCh:
var resultProofRecord *proofDataRecord
Expand All @@ -170,10 +179,10 @@ func (keeper *ProofKeeper) eventLoop() {
for index >= 0 {
m := metaList[index]
if queryBlockID >= m.blockID {
if queryBlockID%m.proposedInterval != 0 { // check
if queryBlockID%m.keepInterval != 0 { // check
break
}
proofID = m.proofID + (queryBlockID-m.blockID)/m.proposedInterval
proofID = m.proofID + (queryBlockID-m.blockID)/m.keepInterval
resultProofRecord = keeper.getProofDataRecord(proofID)
break
}
Expand Down Expand Up @@ -328,34 +337,52 @@ func (keeper *ProofKeeper) IsProposeProofQuery(address common.Address, storageKe
if len(storageKeys) != 0 {
return false
}
// blockID%keeper.opts.keepInterval == 0 is not checked because keepInterval may have been adjusted before.
// blockID%keepInterval == 0 is not checked because keepInterval may have been adjusted before.
_ = blockID
return true
}

// QueryProposeProof is used to get proof which is stored in ancient proof.
func (keeper *ProofKeeper) QueryProposeProof(blockID uint64, stateRoot common.Hash) (*common.AccountResult, error) {
var (
result *common.AccountResult
err error
startTimestamp time.Time
)
startTimestamp = time.Now()
defer func() {
log.Info("Query propose proof",
"block_id", blockID,
"state_root", stateRoot.String(),
"error", err, "elapsed", common.PrettyDuration(time.Since(startTimestamp)))
}()
keeper.queryProofCh <- blockID
resultProofRecord := <-keeper.waitQueryProofCh
if resultProofRecord == nil {
// Maybe the keeper was disabled for a certain period of time before.
return nil, fmt.Errorf("proof is not found")
err = fmt.Errorf("proof is not found, block_id=%d", blockID)
return nil, err
}
if resultProofRecord.BlockID != blockID {
// Maybe the keeper was disabled for a certain period of time before.
return nil, fmt.Errorf("proof is not found due to block is mismatch")
err = fmt.Errorf("proof is not found due to block is mismatch, expected_block_id=%d, actual_block_id=%d",
blockID, resultProofRecord.BlockID)
return nil, err
}
if resultProofRecord.StateRoot.Cmp(stateRoot) != 0 {
// Impossible, unless there is a bug.
return nil, fmt.Errorf("proof is not found due to state root is mismatch")
err = fmt.Errorf("proof is not found due to state root is mismatch, expected_state_root=%s, actual_state_root=%s",
stateRoot.String(), resultProofRecord.StateRoot.String())
return nil, err
}
return &common.AccountResult{
result = &common.AccountResult{
Address: resultProofRecord.Address,
AccountProof: resultProofRecord.AccountProof,
Balance: resultProofRecord.Balance,
CodeHash: resultProofRecord.CodeHash,
Nonce: resultProofRecord.Nonce,
StorageHash: resultProofRecord.StorageHash,
StorageProof: nil,
}, nil
StorageProof: resultProofRecord.StorageProof,
}
return result, nil
}
4 changes: 2 additions & 2 deletions eth/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B
}
stateDb, err := b.eth.BlockChain().StateAt(header.Root)
if err != nil {
return nil, nil, err
return nil, header, err
}
return stateDb, header, nil
}
Expand All @@ -236,7 +236,7 @@ func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockN
}
stateDb, err := b.eth.BlockChain().StateAt(header.Root)
if err != nil {
return nil, nil, err
return nil, header, err
}
return stateDb, header, nil
}
Expand Down
23 changes: 15 additions & 8 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -677,12 +677,8 @@ type StorageResult struct {
}

// GetProof returns the Merkle-proof for a given account and optionally some storage keys.
func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) {
var (
err error
header *types.Header
)
header, err = headerByNumberOrHash(ctx, s.b, blockNrOrHash)
func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (result *AccountResult, err error) {
header, err := headerByNumberOrHash(ctx, s.b, blockNrOrHash)
if err != nil {
return nil, err
}
Expand All @@ -700,9 +696,20 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
}

defer func() {
if proofKeeper := s.b.GetProofKeeper(); err != nil && proofKeeper != nil {
if proofKeeper := s.b.GetProofKeeper(); err != nil && proofKeeper != nil && header.Number != nil {
if proofKeeper.IsProposeProofQuery(address, storageKeys, header.Number.Uint64()) {
// todo
if innerResult, innerError := proofKeeper.QueryProposeProof(header.Number.Uint64(), header.Root); innerError == nil {
result = &AccountResult{
Address: innerResult.Address,
AccountProof: innerResult.AccountProof,
Balance: (*hexutil.Big)(innerResult.Balance),
CodeHash: innerResult.CodeHash,
Nonce: hexutil.Uint64(innerResult.Nonce),
StorageHash: innerResult.StorageHash,
StorageProof: nil,
}
err = nil
}
}
}
}()
Expand Down
9 changes: 5 additions & 4 deletions trie/triedb/pathdb/nodebufferlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ const (
)

type KeepRecord struct {
BlockID uint64
StateRoot common.Hash
BlockID uint64
StateRoot common.Hash
KeepInterval uint64
}

var _ trienodebuffer = &nodebufferlist{}
Expand Down Expand Up @@ -246,7 +247,7 @@ func (nf *nodebufferlist) flush(db ethdb.KeyValueStore, clean *fastcache.Cache,

notifyKeeperFunc := func(buffer *multiDifflayer) bool {
if buffer.block%nf.wpBlocks == 0 {
nf.notifyKeepCh <- &KeepRecord{BlockID: buffer.block, StateRoot: buffer.root}
nf.notifyKeepCh <- &KeepRecord{BlockID: buffer.block, StateRoot: buffer.root, KeepInterval: nf.wpBlocks}
<-nf.waitKeepCh
}
return true
Expand Down Expand Up @@ -483,7 +484,7 @@ func (nf *nodebufferlist) diffToBase() {
}

if buffer.block%nf.wpBlocks == 0 && nf.notifyKeepCh != nil { // maybe keep proof
nf.notifyKeepCh <- &KeepRecord{BlockID: buffer.block, StateRoot: buffer.root}
nf.notifyKeepCh <- &KeepRecord{BlockID: buffer.block, StateRoot: buffer.root, KeepInterval: nf.wpBlocks}
<-nf.waitKeepCh
}

Expand Down

0 comments on commit e6c20fa

Please sign in to comment.