Skip to content

Commit

Permalink
write erigon within statedb
Browse files Browse the repository at this point in the history
  • Loading branch information
envestcc committed Jan 13, 2025
1 parent 368a28a commit 8cefbef
Show file tree
Hide file tree
Showing 16 changed files with 564 additions and 53 deletions.
53 changes: 42 additions & 11 deletions action/protocol/execution/evm/erigonadapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,15 @@ type ErigonStateDBAdapter struct {
snDiff int
}

type ErigonStateDBAdapterDryrun struct {
*ErigonStateDBAdapter
}

func NewErigonStateDBAdapter(adapter *StateDBAdapter,
rw erigonstate.StateWriter,
intra *erigonstate.IntraBlockState,
chainRules *erigonchain.Rules,
) *ErigonStateDBAdapter {
adapter.newContract = func(addr hash.Hash160, account *state.Account) (Contract, error) {
return newContractV2(addr, account, adapter.sm, intra)
}
return &ErigonStateDBAdapter{
StateDBAdapter: adapter,
rw: rw,
Expand All @@ -53,6 +54,19 @@ func NewErigonStateDBAdapter(adapter *StateDBAdapter,
}
}

func NewErigonStateDBAdapterDryrun(adapter *StateDBAdapter,
rw erigonstate.StateWriter,
intra *erigonstate.IntraBlockState,
chainRules *erigonchain.Rules,
) *ErigonStateDBAdapterDryrun {
adapter.newContract = func(addr hash.Hash160, account *state.Account) (Contract, error) {
return newContractV2(addr, account, adapter.sm, intra)
}
return &ErigonStateDBAdapterDryrun{
NewErigonStateDBAdapter(adapter, rw, intra, chainRules),
}
}

func (s *ErigonStateDBAdapter) CreateAccount(evmAddr common.Address) {
s.StateDBAdapter.CreateAccount(evmAddr)
s.intra.CreateAccount(libcommon.Address(evmAddr), true)
Expand Down Expand Up @@ -104,25 +118,42 @@ func (s *ErigonStateDBAdapter) Selfdestruct6780(evmAddr common.Address) {

func (s *ErigonStateDBAdapter) CommitContracts() error {
log.L().Debug("intraBlockState Committing contracts", zap.Uint64("height", s.StateDBAdapter.blockHeight))
err := s.intra.FinalizeTx(s.chainRules, s.rw)
err := s.StateDBAdapter.CommitContracts()
if err != nil {
return err
}
err = s.intra.FinalizeTx(s.chainRules, s.rw)
if err != nil {
return errors.Wrap(err, "failed to finalize tx")
}
return nil
}

func (s *ErigonStateDBAdapter) RevertToSnapshot(sn int) {
log.L().Debug("erigon adapter revert to snapshot", zap.Int("sn", sn), zap.Int("isn", sn+s.snDiff))
s.StateDBAdapter.RevertToSnapshot(sn)
s.intra.RevertToSnapshot(sn + s.snDiff)
// s.intra.RevertToSnapshot(sn + s.snDiff)
}

func (s *ErigonStateDBAdapter) Snapshot() int {
sn := s.StateDBAdapter.Snapshot()
isn := s.intra.Snapshot()
diff := isn - sn
if s.snDiff != 0 && diff != s.snDiff {
log.L().Panic("snapshot diff changed", zap.Int("old", s.snDiff), zap.Int("new", diff))
}
s.snDiff = diff
// isn := s.intra.Snapshot()
// log.L().Debug("erigon adapter snapshot", zap.Int("sn", sn), zap.Int("isn", isn))
// diff := isn - sn
// if s.snDiff != 0 && diff != s.snDiff {
// log.L().Panic("snapshot diff changed", zap.Int("old", s.snDiff), zap.Int("new", diff))
// }
// s.snDiff = diff
return sn
}

func (stateDB *ErigonStateDBAdapterDryrun) GetCode(evmAddr common.Address) []byte {
return stateDB.intra.GetCode(libcommon.Address(evmAddr))
}

// GetCodeSize gets the code size saved in hash
func (stateDB *ErigonStateDBAdapterDryrun) GetCodeSize(evmAddr common.Address) int {
code := stateDB.intra.GetCodeSize(libcommon.Address(evmAddr))
log.T(stateDB.ctx).Debug("Called GetCodeSize.", log.Hex("addrHash", evmAddr[:]))
return code
}
28 changes: 19 additions & 9 deletions action/protocol/execution/evm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,16 +267,26 @@ func ExecuteContract(
return nil, nil, err
}
if erigonsm, ok := sm.(interface {
StateWriter() erigonstate.StateWriter
Intra() *erigonstate.IntraBlockState
Erigon() (erigonstate.StateWriter, *erigonstate.IntraBlockState, bool)
}); ok {
rules := ps.chainConfig.Rules(ps.context.BlockNumber, ps.genesis.IsSumatra(uint64(ps.context.BlockNumber.Int64())), ps.context.Time)
stateDB = NewErigonStateDBAdapter(
stateDB.(*StateDBAdapter),
erigonsm.StateWriter(),
erigonsm.Intra(),
NewErigonRules(&rules),
)
if sw, in, dryrun := erigonsm.Erigon(); sw != nil && in != nil {
rules := ps.chainConfig.Rules(ps.context.BlockNumber, ps.genesis.IsSumatra(uint64(ps.context.BlockNumber.Int64())), ps.context.Time)
if dryrun {
stateDB = NewErigonStateDBAdapterDryrun(
stateDB.(*StateDBAdapter),
sw,
in,
NewErigonRules(&rules),
)
} else {
stateDB = NewErigonStateDBAdapter(
stateDB.(*StateDBAdapter),
sw,
in,
NewErigonRules(&rules),
)
}
}
}

retval, depositGas, remainingGas, contractAddress, statusCode, err := executeInEVM(ctx, ps, stateDB)
Expand Down
1 change: 1 addition & 0 deletions action/protocol/execution/evm/evmstatedbadapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,7 @@ func (stateDB *StateDBAdapter) SetCode(evmAddr common.Address, code []byte) {
stateDB.logError(err)
return
}
log.T(stateDB.ctx).Debug("Called SetCode", log.Hex("addrHash", evmAddr[:]))
contract.SetCode(hash.Hash256b(code), code)
}

Expand Down
5 changes: 5 additions & 0 deletions action/protocol/managers.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ type (
Dock
}

StateManagerWithCloser interface {
StateManager
Close()
}

// Dock defines an interface for protocol to read/write their private data in StateReader/Manager
// data are stored as interface{}, user needs to type-assert on their own upon Unload()
Dock interface {
Expand Down
4 changes: 2 additions & 2 deletions api/coreservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ func (core *coreService) AccountAt(addr address.Address, height uint64) (*iotext
}
span.AddEvent("accountutil.AccountStateWithHeight")
ctx = genesis.WithGenesisContext(ctx, core.bc.Genesis())
ws, err := core.history.StateManagerAt(ctx, height)
ws, err := core.sf.WorkingSetAtHeight(ctx, height)
if err != nil {
return nil, nil, status.Error(codes.NotFound, err.Error())
}
Expand Down Expand Up @@ -2089,7 +2089,7 @@ func (core *coreService) simulateExecutionAt(ctx context.Context, addr address.A
GetBlockTime: core.getBlockTime,
DepositGasFunc: rewarding.DepositGas,
})
ws, err := core.history.StateManagerAt(ctx, height)
ws, err := core.sf.WorkingSetAtHeight(ctx, height)
if err != nil {
return nil, nil, status.Error(codes.Internal, err.Error())
}
Expand Down
2 changes: 1 addition & 1 deletion api/web3server.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func (svr *web3Handler) handleWeb3Req(ctx context.Context, web3Req *gjson.Result
)
defer func(start time.Time) { svr.coreService.Track(ctx, start, method.(string), int64(size), err == nil) }(time.Now())

// log.T(ctx).Debug("handleWeb3Req", zap.String("method", method.(string)), zap.String("requestParams", fmt.Sprintf("%+v", web3Req)))
log.T(ctx).Debug("handleWeb3Req", zap.String("method", method.(string)), zap.String("requestParams", fmt.Sprintf("%+v", web3Req)))
_web3ServerMtc.WithLabelValues(method.(string)).Inc()
_web3ServerMtc.WithLabelValues("requests_total").Inc()
switch method {
Expand Down
15 changes: 10 additions & 5 deletions chainservice/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,11 @@ func (builder *Builder) buildFactory(forTest bool) error {
return errors.Wrapf(err, "failed to create state factory")
}
builder.cs.factory = factory
history, err := builder.createHistoryIndex()
if err != nil {
return errors.Wrapf(err, "failed to create history index")
}
builder.cs.historyIndex = history
// history, err := builder.createHistoryIndex()
// if err != nil {
// return errors.Wrapf(err, "failed to create history index")
// }
// builder.cs.historyIndex = history
return nil
}

Expand Down Expand Up @@ -820,6 +820,11 @@ func (builder *Builder) buildBlockTimeCalculator() (err error) {
if builder.cs.historyIndex != nil {
builder.cs.historyIndex.SetGetBlockTime(builder.cs.blockTimeCalculator.CalculateBlockTime)
}
if f, ok := builder.cs.factory.(interface {
SetGetBlockTime(func(uint64) (time.Time, error))
}); ok {
f.SetGetBlockTime(builder.cs.blockTimeCalculator.CalculateBlockTime)
}
return err
}

Expand Down
9 changes: 8 additions & 1 deletion gasstation/gasstattion.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ func (gs *GasStation) FeeHistory(ctx context.Context, blocks, lastBlock uint64,
log.T(ctx).Warn("Sanitizing fee history length", zap.Uint64("requested", blocks), zap.Uint64("truncated", maxFeeHistory))
blocks = maxFeeHistory
}
if blocks > lastBlock {
blocks = lastBlock
}
for i, p := range rewardPercentiles {
if p < 0 || p > 100 {
return 0, nil, nil, nil, nil, nil, status.Error(codes.InvalidArgument, "percentile must be in [0, 100]")
Expand Down Expand Up @@ -199,7 +202,11 @@ func (gs *GasStation) FeeHistory(ctx context.Context, blocks, lastBlock uint64,
}
fees := make([]*big.Int, 0, len(receipts))
for _, r := range receipts {
fees = append(fees, r.PriorityFee())
if pf := r.PriorityFee(); pf != nil {
fees = append(fees, pf)
} else {
fees = append(fees, big.NewInt(0))
}
}
sort.Slice(fees, func(i, j int) bool {
return fees[i].Cmp(fees[j]) < 0
Expand Down
4 changes: 2 additions & 2 deletions state/factory/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ type (
NewBlockBuilder(context.Context, actpool.ActPool, func(action.Envelope) (*action.SealedEnvelope, error)) (*block.Builder, error)
PutBlock(context.Context, *block.Block) error
WorkingSet(context.Context) (protocol.StateManager, error)
WorkingSetAtHeight(context.Context, uint64) (protocol.StateManager, error)
WorkingSetAtHeight(context.Context, uint64) (protocol.StateManagerWithCloser, error)
}

// factory implements StateFactory interface, tracks changes to account/contract and batch-commits to DB
Expand Down Expand Up @@ -408,7 +408,7 @@ func (sf *factory) WorkingSet(ctx context.Context) (protocol.StateManager, error
return sf.newWorkingSet(ctx, sf.currentChainHeight+1)
}

func (sf *factory) WorkingSetAtHeight(ctx context.Context, height uint64) (protocol.StateManager, error) {
func (sf *factory) WorkingSetAtHeight(ctx context.Context, height uint64) (protocol.StateManagerWithCloser, error) {
if !sf.saveHistory {
return nil, ErrNoArchiveData
}
Expand Down
15 changes: 11 additions & 4 deletions state/factory/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ type HistoryState interface {
// 1. query history account, impl state reader
// 2. query history storage, impl state manager
// 3. simulate in history, impl state manager
StateManagerAt(height uint64) protocol.StateManager
StateManagerAt(height uint64) interface {
protocol.StateManager
Close()
}
}

type HistoryStateIndex struct {
Expand Down Expand Up @@ -107,7 +110,7 @@ func (h *HistoryStateIndex) Start(ctx context.Context) error {
defer tx.Rollback()
r, tsw := erigonstate.NewPlainStateReader(tx), erigonstate.NewPlainStateWriter(tx, tx, 0)
intraBlockState := erigonstate.New(r)
intraBlockState.SetTrace(true)
intraBlockState.SetTrace(false)
hws := &historyWorkingSetRo{
historyWorkingSet: &historyWorkingSet{
workingSet: ws,
Expand Down Expand Up @@ -160,7 +163,7 @@ func (h *HistoryStateIndex) PutBlock(ctx context.Context, blk *block.Block) erro
defer tx.Rollback()
r, tsw := erigonstate.NewPlainStateReader(tx), erigonstate.NewPlainStateWriter(tx, tx, blk.Height())
intraBlockState := erigonstate.New(r)
intraBlockState.SetTrace(true)
intraBlockState.SetTrace(false)

hws := &historyWorkingSet{
workingSet: ws,
Expand Down Expand Up @@ -190,7 +193,7 @@ func (h *HistoryStateIndex) commit(ctx context.Context, tx kv.RwTx, tsw *erigons
if err != nil {
return err
}
intraBlockState.Print(*rules)
// intraBlockState.Print(*rules)

err = tsw.WriteChangeSets()
if err != nil {
Expand Down Expand Up @@ -428,3 +431,7 @@ func (ws *historyWorkingSetRo) PutState(s interface{}, opts ...protocol.StateOpt
}
return h, nil
}

func (ws *historyWorkingSetRo) Close() {
ws.cleanup()
}
Loading

0 comments on commit 8cefbef

Please sign in to comment.