Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
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
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
43 changes: 41 additions & 2 deletions action/protocol/rewarding/reward.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,23 @@ import (
"github.com/iotexproject/iotex-core/v2/action/protocol/staking"
"github.com/iotexproject/iotex-core/v2/pkg/enc"
"github.com/iotexproject/iotex-core/v2/pkg/log"
"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"
)

// rewardHistory is the dummy struct to record a reward. Only key matters.
type rewardHistory struct{}

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

// Serialize serializes reward history state into bytes
func (b rewardHistory) Serialize() ([]byte, error) {
gen := rewardingpb.RewardHistory{}
Expand All @@ -40,6 +51,20 @@ func (b rewardHistory) Serialize() ([]byte, error) {
// Deserialize deserializes bytes into reward history state
func (b *rewardHistory) Deserialize(data []byte) error { return nil }

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

func (b *rewardHistory) Decode(v systemcontracts.GenericValue) error {
return b.Deserialize(v.AuxiliaryData)
}

// rewardAccount stores the unclaimed balance of an account
type rewardAccount struct {
balance *big.Int
Expand Down Expand Up @@ -67,6 +92,20 @@ func (a *rewardAccount) Deserialize(data []byte) error {
return nil
}

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

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

// GrantBlockReward grants the block reward (token) to the block producer
func (p *Protocol) GrantBlockReward(
ctx context.Context,
Expand Down Expand Up @@ -389,7 +428,7 @@ func (p *Protocol) grantToAccount(ctx context.Context, sm protocol.StateManager,
// entry exist
// check if from legacy, and we have started using v2, delete v1
if fromLegacy && useV2Storage(ctx) {
if err := p.deleteStateV1(sm, accKey); err != nil {
if err := p.deleteStateV1(sm, accKey, &rewardAccount{}); err != nil {
return err
}
}
Expand All @@ -416,7 +455,7 @@ func (p *Protocol) claimFromAccount(ctx context.Context, sm protocol.StateManage
return err
}
if fromLegacy && useV2Storage(ctx) {
if err := p.deleteStateV1(sm, accKey); err != nil {
if err := p.deleteStateV1(sm, accKey, &rewardAccount{}); err != nil {
return err
}
}
Expand Down
6 changes: 3 additions & 3 deletions action/protocol/staking/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ const (
_protocolID = "staking"

// _stakingNameSpace is the bucket name for staking state
_stakingNameSpace = "Staking"
_stakingNameSpace = state.StakingNamespace

// _candidateNameSpace is the bucket name for candidate state
_candidateNameSpace = "Candidate"
_candidateNameSpace = state.CandidateNamespace

// CandsMapNS is the bucket name to store candidate map
CandsMapNS = "CandsMap"
CandsMapNS = state.CandsMapNamespace
)

const (
Expand Down
Loading