Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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: 1 addition & 1 deletion action/protocol/execution/evm/contract_adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func newContractAdapter(addr hash.Hash160, account *state.Account, sm protocol.S
if err != nil {
return nil, errors.Wrap(err, "failed to create contract")
}
v2, err := newContractErigon(addr, account, intra)
v2, err := newContractErigon(addr, account.Clone(), intra, sm)
if err != nil {
return nil, errors.Wrap(err, "failed to create contractV2")
}
Expand Down
20 changes: 13 additions & 7 deletions action/protocol/execution/evm/contract_erigon.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,25 @@ import (
"github.com/iotexproject/go-pkgs/hash"
"github.com/pkg/errors"

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

type contractErigon struct {
*state.Account
intra *erigonstate.IntraBlockState
sr protocol.StateReader
addr hash.Hash160
}

func newContractErigon(addr hash.Hash160, account *state.Account, intra *erigonstate.IntraBlockState) (Contract, error) {
func newContractErigon(addr hash.Hash160, account *state.Account, intra *erigonstate.IntraBlockState, sr protocol.StateReader) (Contract, error) {
c := &contractErigon{
Account: account,
intra: intra,
addr: addr,
sr: sr,
}
return c, nil
}
Expand All @@ -32,14 +36,16 @@ func (c *contractErigon) GetCommittedState(key hash.Hash256) ([]byte, error) {
k := libcommon.Hash(key)
v := uint256.NewInt(0)
c.intra.GetCommittedState(libcommon.Address(c.addr), &k, v)
return v.Bytes(), nil
h := hash.BytesToHash256(v.Bytes())
return h[:], nil
}

func (c *contractErigon) GetState(key hash.Hash256) ([]byte, error) {
k := libcommon.Hash(key)
v := uint256.NewInt(0)
c.intra.GetState(libcommon.Address(c.addr), &k, v)
return v.Bytes(), nil
h := hash.BytesToHash256(v.Bytes())
return h[:], nil
}

func (c *contractErigon) SetState(key hash.Hash256, value []byte) error {
Expand All @@ -58,10 +64,10 @@ func (c *contractErigon) SetCode(hash hash.Hash256, code []byte) {

func (c *contractErigon) SelfState() *state.Account {
acc := &state.Account{}
acc.SetPendingNonce(c.intra.GetNonce(libcommon.Address(c.addr)))
acc.AddBalance(c.intra.GetBalance(libcommon.Address(c.addr)).ToBig())
codeHash := c.intra.GetCodeHash(libcommon.Address(c.addr))
acc.CodeHash = codeHash[:]
_, err := c.sr.State(acc, protocol.LegacyKeyOption(c.addr), protocol.ErigonStoreOnlyOption())
if err != nil {
log.S().Panicf("failed to load account %x: %v", c.addr, err)
}
return acc
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func NewErigonStateDBAdapterDryrun(adapter *StateDBAdapter,
) *ErigonStateDBAdapterDryrun {
a := NewErigonStateDBAdapter(adapter, intra)
adapter.newContract = func(addr hash.Hash160, account *state.Account) (Contract, error) {
return newContractErigon(addr, account, intra)
return newContractErigon(addr, account, intra, adapter.sm)
}
return &ErigonStateDBAdapterDryrun{
ErigonStateDBAdapter: a,
Expand Down
43 changes: 40 additions & 3 deletions action/protocol/rewarding/fund.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
"github.com/iotexproject/iotex-core/v2/systemcontracts"
)

type Fund = fund

// fund stores the balance of the rewarding fund. The difference between total and available balance should be
// equal to the unclaimed balance in all reward accounts
type fund struct {
Expand Down Expand Up @@ -59,17 +61,52 @@ func (f *fund) Deserialize(data []byte) error {
}

func (f *fund) Encode() (systemcontracts.GenericValue, error) {
data, err := f.Serialize()
d1, err := proto.Marshal(&rewardingpb.Fund{
TotalBalance: f.totalBalance.String(),
})
if err != nil {
return systemcontracts.GenericValue{}, err
}
d2, err := proto.Marshal(&rewardingpb.Fund{
UnclaimedBalance: f.unclaimedBalance.String(),
})
if err != nil {
return systemcontracts.GenericValue{}, err
}
return systemcontracts.GenericValue{
AuxiliaryData: data,
PrimaryData: d1,
SecondaryData: d2,
}, nil
}

func (f *fund) Decode(v systemcontracts.GenericValue) error {
return f.Deserialize(v.AuxiliaryData)
gen1 := rewardingpb.Fund{}
if err := proto.Unmarshal(v.PrimaryData, &gen1); err != nil {
return err
}
var totalBalance = big.NewInt(0)
if len(gen1.TotalBalance) > 0 {
b, ok := new(big.Int).SetString(gen1.TotalBalance, 10)
if !ok {
return errors.Errorf("failed to set total balance from string: %s", gen1.TotalBalance)
}
totalBalance = b
}
gen2 := rewardingpb.Fund{}
if err := proto.Unmarshal(v.SecondaryData, &gen2); err != nil {
return err
}
var unclaimedBalance = big.NewInt(0)
if len(gen2.UnclaimedBalance) > 0 {
b, ok := new(big.Int).SetString(gen2.UnclaimedBalance, 10)
if !ok {
return errors.Errorf("failed to set unclaimed balance from string: %s", gen2.UnclaimedBalance)
}
unclaimedBalance = b
}
f.totalBalance = totalBalance
f.unclaimedBalance = unclaimedBalance
return nil
}

// Deposit deposits token into the rewarding fund
Expand Down
36 changes: 32 additions & 4 deletions action/protocol/rewarding/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
accountutil "github.com/iotexproject/iotex-core/v2/action/protocol/account/util"
"github.com/iotexproject/iotex-core/v2/action/protocol/rolldpos"
"github.com/iotexproject/iotex-core/v2/blockchain/genesis"
"github.com/iotexproject/iotex-core/v2/pkg/enc"
"github.com/iotexproject/iotex-core/v2/pkg/log"
"github.com/iotexproject/iotex-core/v2/state"
)
Expand Down Expand Up @@ -102,6 +103,13 @@ func FindProtocol(registry *protocol.Registry) *Protocol {
func (p *Protocol) CreatePreStates(ctx context.Context, sm protocol.StateManager) error {
g := genesis.MustExtractGenesisContext(ctx)
blkCtx := protocol.MustGetBlockCtx(ctx)
// set current block reward not granted for erigon db
var indexBytes [8]byte
enc.MachineEndian.PutUint64(indexBytes[:], blkCtx.BlockHeight)
err := p.deleteState(ctx, sm, append(_blockRewardHistoryKeyPrefix, indexBytes[:]...), &rewardHistory{}, protocol.ErigonStoreOnlyOption())
if err != nil && !errors.Is(err, state.ErrErigonStoreNotSupported) {
return err
}
switch blkCtx.BlockHeight {
case g.AleutianBlockHeight:
return p.SetReward(ctx, sm, g.AleutianEpochReward(), false)
Expand Down Expand Up @@ -348,10 +356,11 @@ func (p *Protocol) putState(ctx context.Context, sm protocol.StateManager, key [
return p.putStateV1(sm, key, value)
}

func (p *Protocol) putStateV1(sm protocol.StateManager, key []byte, value interface{}) error {
func (p *Protocol) putStateV1(sm protocol.StateManager, key []byte, value interface{}, opts ...protocol.StateOption) error {
orgKey := append(p.keyPrefix, key...)
keyHash := hash.Hash160b(orgKey)
_, err := sm.PutState(value, protocol.LegacyKeyOption(keyHash), protocol.ErigonStoreKeyOption(orgKey))
opts = append(opts, protocol.LegacyKeyOption(keyHash), protocol.ErigonStoreKeyOption(orgKey))
_, err := sm.PutState(value, opts...)
return err
}

Expand All @@ -361,10 +370,29 @@ func (p *Protocol) putStateV2(sm protocol.StateManager, key []byte, value interf
return err
}

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

func (p *Protocol) deleteStateV1(sm protocol.StateManager, key []byte, obj any, opts ...protocol.StateOption) error {
orgKey := append(p.keyPrefix, key...)
keyHash := hash.Hash160b(orgKey)
_, err := sm.DelState(protocol.LegacyKeyOption(keyHash), protocol.ObjectOption(obj), protocol.ErigonStoreKeyOption(orgKey))
opt := append(opts, protocol.LegacyKeyOption(keyHash), protocol.ObjectOption(obj), protocol.ErigonStoreKeyOption(orgKey))
_, err := sm.DelState(opt...)
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, value any, opts ...protocol.StateOption) error {
k := append(p.keyPrefix, key...)
opt := append(opts, protocol.KeyOption(k), protocol.ObjectOption(value), protocol.NamespaceOption(_v2RewardingNamespace))
_, err := sm.DelState(opt...)
if errors.Cause(err) == state.ErrStateNotExist {
// don't care if not exist
return nil
Expand Down
21 changes: 21 additions & 0 deletions action/protocol/rewarding/reward.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"math/big"

"github.com/pkg/errors"
"go.uber.org/zap"
"google.golang.org/protobuf/proto"

"github.com/iotexproject/go-pkgs/hash"
Expand All @@ -29,6 +30,8 @@ import (
"github.com/iotexproject/iotex-core/v2/systemcontracts"
)

type RewardHistory = rewardHistory

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

Expand Down Expand Up @@ -114,6 +117,24 @@ func (p *Protocol) GrantBlockReward(
) (*action.Log, error) {
actionCtx := protocol.MustGetActionCtx(ctx)
blkCtx := protocol.MustGetBlockCtx(ctx)
fCtx := protocol.MustGetFeatureCtx(ctx)

if fCtx.UseV2Storage {
var indexBytes [8]byte
enc.MachineEndian.PutUint64(indexBytes[:], blkCtx.BlockHeight)
key := append(_blockRewardHistoryKeyPrefix, indexBytes[:]...)
err := p.deleteStateV1(sm, key, &rewardHistory{}, protocol.ErigonStoreOnlyOption())
if err != nil && !errors.Is(err, state.ErrErigonStoreNotSupported) {
return nil, err
}
defer func() {
err = p.putStateV1(sm, key, &rewardHistory{}, protocol.ErigonStoreOnlyOption())
if err != nil && !errors.Is(err, state.ErrErigonStoreNotSupported) {
log.L().Panic("failed to put block reward history in Erigon store", zap.Error(err))
}
}()
}

if err := p.assertNoRewardYet(ctx, sm, _blockRewardHistoryKeyPrefix, blkCtx.BlockHeight); err != nil {
return nil, err
}
Expand Down
46 changes: 30 additions & 16 deletions action/protocol/staking/candidate.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (

"github.com/iotexproject/iotex-core/v2/action"
"github.com/iotexproject/iotex-core/v2/action/protocol/staking/stakingpb"
"github.com/iotexproject/iotex-core/v2/pkg/util/byteutil"
"github.com/iotexproject/iotex-core/v2/state"
"github.com/iotexproject/iotex-core/v2/systemcontracts"
)
Expand Down Expand Up @@ -418,7 +417,7 @@ func (l *CandidateList) Deserialize(buf []byte) error {
}

// Encode encodes candidate list into generic value
func (l *CandidateList) Encode() ([][]byte, []systemcontracts.GenericValue, error) {
func (l *CandidateList) Encodes() ([][]byte, []systemcontracts.GenericValue, error) {
var (
keys [][]byte
values []systemcontracts.GenericValue
Expand All @@ -429,29 +428,44 @@ func (l *CandidateList) Encode() ([][]byte, []systemcontracts.GenericValue, erro
if err != nil {
return nil, nil, errors.Wrap(err, "failed to encode candidate")
}
gv.AuxiliaryData = byteutil.Uint64ToBytes(uint64(idx))
var nextAddr []byte
if idx < len(*l)-1 {
nextAddr = (*l)[idx+1].GetIdentifier().Bytes()
}
gv.AuxiliaryData = nextAddr
keys = append(keys, key)
values = append(values, gv)
}
return keys, values, nil
}

// Decode decodes candidate list from generic value
func (l *CandidateList) Decode(keys [][]byte, gvs []systemcontracts.GenericValue) error {
// reconstruct candidate list
// the order of keys and gvs are guaranteed to be the same
candidateMap := make(map[uint64]*Candidate)
for _, gv := range gvs {
func (l *CandidateList) Decodes(keys [][]byte, gvs []systemcontracts.GenericValue) error {
if len(keys) != len(gvs) {
return errors.New("mismatched keys and generic values length")
}
if len(keys) == 0 {
*l = CandidateList{}
return nil
}

candidates, err := state.DecodeOrderedKvList(keys, gvs, func(k []byte, v systemcontracts.GenericValue) (*Candidate, string, string, error) {
c := &Candidate{}
if err := c.Decode(gv); err != nil {
return errors.Wrap(err, "failed to decode candidate")
if err := c.Decode(v); err != nil {
return nil, "", "", errors.Wrap(err, "failed to decode candidate")
}
idx := byteutil.BytesToUint64(gv.AuxiliaryData)
candidateMap[idx] = c
}
candidates := make(CandidateList, 0, len(candidateMap))
for i := 0; i < len(candidateMap); i++ {
candidates = append(candidates, candidateMap[uint64(i)])
var next string
if len(v.AuxiliaryData) > 0 {
nextAddr, err := address.FromBytes(v.AuxiliaryData)
if err != nil {
return nil, "", "", errors.Wrap(err, "failed to get next candidate address")
}
next = nextAddr.String()
}
return c, c.GetIdentifier().String(), next, nil
})
if err != nil {
return errors.Wrap(err, "failed to decode candidate list")
}
*l = candidates
return nil
Expand Down
Loading
Loading