Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
24783b1
systemcontracts for erigon
envestcc Aug 21, 2025
b5c7922
define state namespaces
envestcc Aug 21, 2025
4e9288a
contract backend
envestcc Aug 21, 2025
e37f09e
contract storage
envestcc Aug 21, 2025
a16e573
workingset object store
envestcc Aug 21, 2025
c7fa24a
workingsetstore as kvstore
envestcc Aug 21, 2025
df5d789
store rewarding
envestcc Aug 21, 2025
085526f
store poll
envestcc Aug 21, 2025
3469fc0
store staking
envestcc Aug 22, 2025
6b7724a
read staking states from erigondb, and deprecat staking index db
envestcc Aug 22, 2025
2d00d27
secondaryOnly
envestcc Aug 29, 2025
ad4c6b0
Store staking in trie (#4680)
CoderZhi Sep 2, 2025
a95f8a2
snapshot/revert views (#4669)
CoderZhi Sep 3, 2025
2bea890
fix two unit tests and refactor matchbuckettype
CoderZhi Sep 1, 2025
6e70d2e
introduce event processor
CoderZhi Sep 1, 2025
5039413
refactor two functions
CoderZhi Sep 1, 2025
a2ebe85
candidate center with nft staking
CoderZhi Aug 30, 2025
17e6f5a
fix pick error
envestcc Sep 3, 2025
99c6315
store all contract staking state in erigon
envestcc Sep 3, 2025
9f16b20
resume historical views
envestcc Sep 3, 2025
5afb1fe
draft: memory candidate votes instead of buckets
envestcc Sep 4, 2025
23020e3
draft: refactor
envestcc Sep 8, 2025
b797450
candidate votes for bucket type indexer
envestcc Sep 9, 2025
e8c02f6
vote view store as contract
envestcc Sep 9, 2025
7d6731c
fix ws dead lock
envestcc Sep 9, 2025
ec88710
fix systemcontractindex
envestcc Sep 9, 2025
752cc01
fix blockindex
envestcc Sep 9, 2025
5d9c31c
fix stuff
envestcc Sep 9, 2025
4622115
fix bugs
envestcc Sep 9, 2025
58556ea
fix systemcontractindex
envestcc Sep 10, 2025
a853e6a
fix blockindex
envestcc Sep 10, 2025
113a1ec
fix ws
envestcc Sep 10, 2025
086d421
fix votes
envestcc Sep 10, 2025
4643607
unit test for nft event handler
CoderZhi Sep 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions action/protocol/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ type (
NotSlashUnproductiveDelegates bool
CandidateBLSPublicKey bool
NotUseMinSelfStakeToBeActive bool
StoreVoteOfNFTBucketIntoView bool
}

// FeatureWithHeightCtx provides feature check functions.
Expand Down Expand Up @@ -327,6 +328,7 @@ func WithFeatureCtx(ctx context.Context) context.Context {
NotSlashUnproductiveDelegates: !g.IsToBeEnabled(height),
CandidateBLSPublicKey: g.IsToBeEnabled(height),
NotUseMinSelfStakeToBeActive: !g.IsToBeEnabled(height),
StoreVoteOfNFTBucketIntoView: !g.IsToBeEnabled(height),
},
)
}
Expand Down
6 changes: 3 additions & 3 deletions action/protocol/execution/evm/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import (

const (
// CodeKVNameSpace is the bucket name for code
CodeKVNameSpace = "Code"
CodeKVNameSpace = state.CodeKVNameSpace
// ContractKVNameSpace is the bucket name for contract data storage
ContractKVNameSpace = "Contract"
ContractKVNameSpace = state.ContractKVNameSpace
// PreimageKVNameSpace is the bucket name for preimage data storage
PreimageKVNameSpace = "Preimage"
PreimageKVNameSpace = state.PreimageKVNameSpace
)

type (
Expand Down
20 changes: 16 additions & 4 deletions action/protocol/execution/evm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package evm
import (
"bytes"
"context"
"encoding/hex"
"math"
"math/big"
"time"
Expand Down Expand Up @@ -326,10 +327,7 @@ func ExecuteContract(

if ps.featureCtx.SetRevertMessageToReceipt && receipt.Status == uint64(iotextypes.ReceiptStatus_ErrExecutionReverted) && retval != nil && bytes.Equal(retval[:4], _revertSelector) {
// in case of the execution revert error, parse the retVal and add to receipt
data := retval[4:]
msgLength := byteutil.BytesToUint64BigEndian(data[56:64])
revertMsg := string(data[64 : 64+msgLength])
receipt.SetExecutionRevertMsg(revertMsg)
receipt.SetExecutionRevertMsg(ExtractRevertMessage(retval))
}
log.S().Debugf("Retval: %x, Receipt: %+v, %v", retval, receipt, err)
if tCtx, ok := GetTracerCtx(ctx); ok && tCtx.CaptureTx != nil {
Expand Down Expand Up @@ -765,3 +763,17 @@ func SimulateExecution(
))
return ExecuteContract(ctx, sm, ex)
}

// ExtractRevertMessage extracts the revert message from the return value
func ExtractRevertMessage(ret []byte) string {
if len(ret) < 4 {
return hex.EncodeToString(ret)
}
if !bytes.Equal(ret[:4], _revertSelector) {
return hex.EncodeToString(ret)
}
data := ret[4:]
msgLength := byteutil.BytesToUint64BigEndian(data[56:64])
revertMsg := string(data[64 : 64+msgLength])
return revertMsg
}
24 changes: 21 additions & 3 deletions action/protocol/managers.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,30 @@ func CreateStateConfig(opts ...StateOption) (*StateConfig, error) {
return &cfg, nil
}

// ObjectOption sets the object for call
func ObjectOption(obj any) StateOption {
return func(cfg *StateConfig) error {
cfg.Object = obj
return nil
}
}

// SecondaryOnlyOption sets the option to only access secondary workingset store
func SecondaryOnlyOption() StateOption {
return func(cfg *StateConfig) error {
cfg.SecondaryOnly = true
return nil
}
}

type (
// StateConfig is the config for accessing stateDB
StateConfig struct {
Namespace string // namespace used by state's storage
Key []byte
Keys [][]byte
Namespace string // namespace used by state's storage
Key []byte
Keys [][]byte
Object any // object used by state's storage
SecondaryOnly bool // only access secondary workingset store
}

// StateOption sets parameter for access state
Expand Down
67 changes: 53 additions & 14 deletions action/protocol/mock_protocol.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions action/protocol/poll/blockmeta.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ import (
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/timestamppb"

"github.com/iotexproject/iotex-address/address"

"github.com/iotexproject/iotex-core/v2/action/protocol"
"github.com/iotexproject/iotex-core/v2/action/protocol/poll/blockmetapb"
"github.com/iotexproject/iotex-core/v2/state"
"github.com/iotexproject/iotex-core/v2/systemcontracts"
)

// BlockMeta is a struct to store block metadata
Expand All @@ -22,6 +27,8 @@ type BlockMeta struct {
MintTime time.Time
}

var _ state.ContractStorageStandard = (*BlockMeta)(nil)

// NewBlockMeta constructs new blockmeta struct with given fieldss
func NewBlockMeta(height uint64, producer string, mintTime time.Time) *BlockMeta {
return &BlockMeta{
Expand Down Expand Up @@ -70,3 +77,14 @@ func (bm *BlockMeta) LoadProto(pb *blockmetapb.BlockMeta) error {
bm.MintTime = mintTime.UTC()
return nil
}

func (bm *BlockMeta) ContractStorageAddress(ns string, key []byte) (address.Address, error) {
if ns != protocol.SystemNamespace {
return nil, errors.Errorf("invalid namespace %s, expected %s", ns, protocol.SystemNamespace)
}
return systemcontracts.SystemContracts[systemcontracts.PollBlockMetaContractIndex].Address, nil
}

func (bm *BlockMeta) New() state.ContractStorageStandard {
return &BlockMeta{}
}
5 changes: 3 additions & 2 deletions action/protocol/poll/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ func shiftCandidates(sm protocol.StateManager) (uint64, error) {
if stateHeight != putStateHeight {
return 0, errors.Wrap(ErrInconsistentHeight, "failed to shift candidates")
}
if delStateHeight, err = sm.DelState(protocol.KeyOption(nextKey[:]), protocol.NamespaceOption(protocol.SystemNamespace)); err != nil {
if delStateHeight, err = sm.DelState(protocol.KeyOption(nextKey[:]), protocol.NamespaceOption(protocol.SystemNamespace), protocol.ObjectOption(&state.CandidateList{})); err != nil {
return 0, errors.Wrap(
err,
"failed to delete next candidatelist after shifting",
Expand Down Expand Up @@ -306,7 +306,7 @@ func shiftProbationList(sm protocol.StateManager) (uint64, error) {
if stateHeight != putStateHeight {
return 0, errors.Wrap(ErrInconsistentHeight, "failed to shift candidates")
}
if delStateHeight, err = sm.DelState(protocol.KeyOption(nextKey[:]), protocol.NamespaceOption(protocol.SystemNamespace)); err != nil {
if delStateHeight, err = sm.DelState(protocol.KeyOption(nextKey[:]), protocol.NamespaceOption(protocol.SystemNamespace), protocol.ObjectOption(&vote.ProbationList{})); err != nil {
return 0, errors.Wrap(
err,
"failed to delete next probationlist after shifting",
Expand Down Expand Up @@ -341,6 +341,7 @@ func allBlockMetasFromDB(sr protocol.StateReader, blocksInEpoch uint64) ([]*Bloc
protocol.KeysOption(func() ([][]byte, error) {
return keys, nil
}),
protocol.ObjectOption(&BlockMeta{}),
)
if err != nil {
return nil, err
Expand Down
52 changes: 46 additions & 6 deletions action/protocol/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

"github.com/iotexproject/iotex-core/v2/action"
"github.com/iotexproject/iotex-core/v2/pkg/log"
"github.com/iotexproject/iotex-core/v2/state"
)

var (
Expand All @@ -27,7 +28,7 @@ var (

const (
// SystemNamespace is the namespace to store system information such as candidates/probationList/unproductiveDelegates
SystemNamespace = "System"
SystemNamespace = state.SystemNamespace
)

// Protocol defines the protocol interfaces atop IoTeX blockchain
Expand All @@ -44,6 +45,11 @@ type Starter interface {
Start(context.Context, StateReader) (View, error)
}

// Viewer defines the viewer interface for the protocol
type Viewer interface {
ViewAt(context.Context, StateReader) (View, error)
}

// GenesisStateCreator creates some genesis states
type GenesisStateCreator interface {
CreateGenesisStates(context.Context, StateManager) error
Expand Down Expand Up @@ -115,19 +121,53 @@ type (
Fork() View
Snapshot() int
Revert(int) error
Commit(context.Context, StateReader) error
Commit(context.Context, StateManager) error
}

// Views stores the view for all protocols
Views struct {
vm map[string]View
snapshotID int
snapshots map[int]map[string]int
vm map[string]View
}
)

func NewViews() *Views {
return &Views{
vm: make(map[string]View),
snapshotID: 0,
snapshots: make(map[int]map[string]int),
vm: make(map[string]View),
}
}

func (views *Views) Snapshot() int {
views.snapshotID++
views.snapshots[views.snapshotID] = make(map[string]int)
keys := make([]string, 0, len(views.vm))
for key := range views.vm {
keys = append(keys, key)
}
for _, key := range keys {
views.snapshots[views.snapshotID][key] = views.vm[key].Snapshot()
}
return views.snapshotID
}

func (views *Views) Revert(id int) error {
if id > views.snapshotID || id < 0 {
return errors.Errorf("invalid snapshot id %d, max id is %d", id, views.snapshotID)
}
for k, v := range views.snapshots[id] {
if err := views.vm[k].Revert(v); err != nil {
return err
}
}
views.snapshotID = id
// clean up snapshots that are not needed anymore
for i := id + 1; i <= views.snapshotID; i++ {
delete(views.snapshots, i)
}
return nil
}

func (views *Views) Fork() *Views {
Expand All @@ -138,9 +178,9 @@ func (views *Views) Fork() *Views {
return fork
}

func (views *Views) Commit(ctx context.Context, sr StateReader) error {
func (views *Views) Commit(ctx context.Context, sm StateManager) error {
for _, view := range views.vm {
if err := view.Commit(ctx, sr); err != nil {
if err := view.Commit(ctx, sm); err != nil {
return err
}
}
Expand Down
25 changes: 25 additions & 0 deletions action/protocol/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,28 @@ func (r *Registry) StartAll(ctx context.Context, sr StateReader) (*Views, error)
}
return allViews, nil
}

// ViewsAt returns the views of all protocols at a specific state
func (r *Registry) ViewsAt(ctx context.Context, sr StateReader) (*Views, error) {
if r == nil {
return nil, nil
}
r.mu.RLock()
defer r.mu.RUnlock()
allViews := NewViews()
for _, p := range r.all() {
s, ok := p.(Viewer)
if !ok {
continue
}
view, err := s.ViewAt(ctx, sr)
if err != nil {
return nil, errors.Wrapf(err, "failed to start protocol %s", reflect.TypeOf(p))
}
if view == nil {
continue
}
allViews.Write(p.Name(), view)
}
return allViews, nil
}
Loading