Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9337f8f
systemcontracts for erigon
envestcc Aug 21, 2025
5a99359
define state namespaces
envestcc Aug 21, 2025
ab32d01
contract backend
envestcc Aug 21, 2025
84d4c14
contract storage
envestcc Aug 21, 2025
35c797e
workingset object store
envestcc Aug 21, 2025
4764e23
workingsetstore as kvstore
envestcc Aug 21, 2025
cec240f
systemcontract efficiency
envestcc Aug 22, 2025
e769614
address comment
envestcc Aug 22, 2025
3830705
address comment
envestcc Aug 25, 2025
4931c19
fix lock
envestcc Aug 31, 2025
791c488
fix test
envestcc Aug 31, 2025
b69dd76
Merge branch 'master' into erigon-store-storage
CoderZhi Sep 4, 2025
ada13e8
Merge branch 'master' into erigon-store-storage
CoderZhi Sep 8, 2025
ebb0d13
refactor: together erigon store
envestcc Sep 11, 2025
ffe12f8
store account as contract storage
envestcc Sep 11, 2025
2209d32
systemcontract auth
envestcc Sep 11, 2025
2efec64
store account additional fields in contract
envestcc Sep 11, 2025
7ac143c
fix test
envestcc Sep 12, 2025
9653838
address comment
envestcc Sep 15, 2025
134cbdc
address comment
envestcc Sep 15, 2025
151654e
refactor
CoderZhi Sep 17, 2025
3777364
fix owner issue
CoderZhi Sep 17, 2025
6a3082e
fix unit test
CoderZhi Sep 18, 2025
edb5f09
address comment
envestcc Sep 25, 2025
804d2f7
Merge remote-tracking branch 'upstream/master' into erigon-store-storage
envestcc Sep 25, 2025
c0a6084
object registry
envestcc Sep 25, 2025
dfd1c27
fix registry
envestcc Sep 25, 2025
08cf2b9
store rewarding
envestcc Aug 21, 2025
fbab5ea
store poll
envestcc Aug 21, 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
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 @@ -762,3 +760,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
}
9 changes: 9 additions & 0 deletions action/protocol/managers.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,21 @@ 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
}
}

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

// StateOption sets parameter for access state
Expand Down
22 changes: 22 additions & 0 deletions action/protocol/poll/blockmeta.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import (
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/timestamppb"

"github.com/iotexproject/iotex-core/v2/action/protocol"
"github.com/iotexproject/iotex-core/v2/action/protocol/poll/blockmetapb"
"github.com/iotexproject/iotex-core/v2/pkg/util/assertions"
"github.com/iotexproject/iotex-core/v2/state/factory/erigonstore"
"github.com/iotexproject/iotex-core/v2/systemcontracts"
)

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

func init() {
assertions.MustNoError(erigonstore.GetObjectStorageRegistry().RegisterPollBlockMeta(protocol.SystemNamespace, &BlockMeta{}))
}

// 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 +78,17 @@ func (bm *BlockMeta) LoadProto(pb *blockmetapb.BlockMeta) error {
bm.MintTime = mintTime.UTC()
return nil
}

// Encode encodes BlockMeta into a GenericValue
func (bm *BlockMeta) Encode() (systemcontracts.GenericValue, error) {
data, err := bm.Serialize()
if err != nil {
return systemcontracts.GenericValue{}, errors.Wrap(err, "failed to serialize block meta")
}
return systemcontracts.GenericValue{PrimaryData: data}, nil
}

// Decode decodes a GenericValue into BlockMeta
func (bm *BlockMeta) Decode(data systemcontracts.GenericValue) error {
return bm.Deserialize(data.PrimaryData)
}
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
3 changes: 2 additions & 1 deletion 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 Down
41 changes: 41 additions & 0 deletions action/protocol/rewarding/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ import (
"google.golang.org/protobuf/proto"

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

"github.com/iotexproject/iotex-core/v2/action/protocol"
"github.com/iotexproject/iotex-core/v2/action/protocol/rewarding/rewardingpb"
"github.com/iotexproject/iotex-core/v2/blockchain/genesis"
"github.com/iotexproject/iotex-core/v2/pkg/util/assertions"
"github.com/iotexproject/iotex-core/v2/state"
"github.com/iotexproject/iotex-core/v2/state/factory/erigonstore"
"github.com/iotexproject/iotex-core/v2/systemcontracts"
)

// admin stores the admin data of the rewarding protocol
Expand All @@ -29,6 +34,14 @@ type admin struct {
productivityThreshold uint64
}

func init() {
registry := erigonstore.GetObjectStorageRegistry()
assertions.MustNoError(registry.RegisterRewardingV1(state.AccountKVNamespace, &admin{}))
assertions.MustNoError(registry.RegisterRewardingV1(state.AccountKVNamespace, &exempt{}))
assertions.MustNoError(registry.RegisterRewardingV2(_v2RewardingNamespace, &admin{}))
assertions.MustNoError(registry.RegisterRewardingV2(_v2RewardingNamespace, &exempt{}))
}

// Serialize serializes admin state into bytes
func (a admin) Serialize() ([]byte, error) {
gen := rewardingpb.Admin{
Expand Down Expand Up @@ -71,6 +84,20 @@ func (a *admin) Deserialize(data []byte) error {
return nil
}

func (a *admin) Encode() (systemcontracts.GenericValue, error) {
data, err := a.Serialize()
if err != nil {
return systemcontracts.GenericValue{}, err
}
return systemcontracts.GenericValue{
AuxiliaryData: data,
}, nil
}

func (a *admin) Decode(v systemcontracts.GenericValue) error {
return a.Deserialize(v.AuxiliaryData)
}

func (a *admin) grantFoundationBonus(epoch uint64) bool {
return epoch <= a.foundationBonusLastEpoch
}
Expand Down Expand Up @@ -106,6 +133,20 @@ func (e *exempt) Deserialize(data []byte) error {
return nil
}

func (e *exempt) Encode() (systemcontracts.GenericValue, error) {
data, err := e.Serialize()
if err != nil {
return systemcontracts.GenericValue{}, err
}
return systemcontracts.GenericValue{
AuxiliaryData: data,
}, nil
}

func (e *exempt) Decode(v systemcontracts.GenericValue) error {
return e.Deserialize(v.AuxiliaryData)
}

// CreateGenesisStates initializes the rewarding protocol by setting the original admin, block and epoch reward
func (p *Protocol) CreateGenesisStates(
ctx context.Context,
Expand Down
23 changes: 23 additions & 0 deletions action/protocol/rewarding/fund.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ import (
"github.com/iotexproject/iotex-core/v2/action/protocol"
accountutil "github.com/iotexproject/iotex-core/v2/action/protocol/account/util"
"github.com/iotexproject/iotex-core/v2/action/protocol/rewarding/rewardingpb"
"github.com/iotexproject/iotex-core/v2/pkg/util/assertions"
"github.com/iotexproject/iotex-core/v2/state"
"github.com/iotexproject/iotex-core/v2/state/factory/erigonstore"
"github.com/iotexproject/iotex-core/v2/systemcontracts"
)

// fund stores the balance of the rewarding fund. The difference between total and available balance should be
Expand All @@ -29,6 +32,12 @@ type fund struct {
unclaimedBalance *big.Int
}

func init() {
registry := erigonstore.GetObjectStorageRegistry()
assertions.MustNoError(registry.RegisterRewardingV1(state.AccountKVNamespace, &fund{}))
assertions.MustNoError(registry.RegisterRewardingV2(_v2RewardingNamespace, &fund{}))
}

// Serialize serializes fund state into bytes
func (f fund) Serialize() ([]byte, error) {
gen := rewardingpb.Fund{
Expand Down Expand Up @@ -57,6 +66,20 @@ func (f *fund) Deserialize(data []byte) error {
return nil
}

func (f *fund) Encode() (systemcontracts.GenericValue, error) {
data, err := f.Serialize()
if err != nil {
return systemcontracts.GenericValue{}, err
}
return systemcontracts.GenericValue{
AuxiliaryData: data,
}, nil
}

func (f *fund) Decode(v systemcontracts.GenericValue) error {
return f.Deserialize(v.AuxiliaryData)
}

// Deposit deposits token into the rewarding fund
func (p *Protocol) Deposit(
ctx context.Context,
Expand Down
25 changes: 4 additions & 21 deletions action/protocol/rewarding/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
const (
// TODO: it works only for one instance per protocol definition now
_protocolID = "rewarding"
_v2RewardingNamespace = "Rewarding"
_v2RewardingNamespace = state.RewardingNamespace
)

var (
Expand Down Expand Up @@ -138,7 +138,7 @@ func (p *Protocol) migrateValue(sm protocol.StateManager, key []byte, value inte
if err := p.putStateV2(sm, key, value); err != nil {
return err
}
return p.deleteStateV1(sm, key)
return p.deleteStateV1(sm, key, value)
}

func (p *Protocol) setFoundationBonusExtension(ctx context.Context, sm protocol.StateManager) error {
Expand Down Expand Up @@ -359,26 +359,9 @@ func (p *Protocol) putStateV2(sm protocol.StateManager, key []byte, value interf
return err
}

func (p *Protocol) deleteState(ctx context.Context, sm protocol.StateManager, key []byte) error {
if useV2Storage(ctx) {
return p.deleteStateV2(sm, key)
}
return p.deleteStateV1(sm, key)
}

func (p *Protocol) deleteStateV1(sm protocol.StateManager, key []byte) error {
func (p *Protocol) deleteStateV1(sm protocol.StateManager, key []byte, obj any) error {
keyHash := hash.Hash160b(append(p.keyPrefix, key...))
_, err := sm.DelState(protocol.LegacyKeyOption(keyHash))
if errors.Cause(err) == state.ErrStateNotExist {
// don't care if not exist
return nil
}
return err
}

func (p *Protocol) deleteStateV2(sm protocol.StateManager, key []byte) error {
k := append(p.keyPrefix, key...)
_, err := sm.DelState(protocol.KeyOption(k), protocol.NamespaceOption(_v2RewardingNamespace))
_, err := sm.DelState(protocol.LegacyKeyOption(keyHash), protocol.ObjectOption(obj))
if errors.Cause(err) == state.ErrStateNotExist {
// don't care if not exist
return nil
Expand Down
Loading
Loading