Skip to content

Commit

Permalink
not set nonce in staking
Browse files Browse the repository at this point in the history
  • Loading branch information
envestcc committed Jun 17, 2024
1 parent 4763731 commit e56a50a
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 71 deletions.
20 changes: 0 additions & 20 deletions action/protocol/execution/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (

"github.com/iotexproject/iotex-core/action"
"github.com/iotexproject/iotex-core/action/protocol"
accountutil "github.com/iotexproject/iotex-core/action/protocol/account/util"
"github.com/iotexproject/iotex-core/action/protocol/execution/evm"
"github.com/iotexproject/iotex-core/pkg/log"
)
Expand Down Expand Up @@ -84,25 +83,6 @@ func (p *Protocol) Handle(ctx context.Context, act action.Action, sm protocol.St
return receipt, nil
}

// HandleCrossProtocol handles an execution from another protocol
func (p *Protocol) HandleCrossProtocol(ctx context.Context, act action.Action, sm protocol.StateManager) (*action.Receipt, error) {
receipt, err := p.Handle(ctx, act, sm)
if err != nil {
return nil, errors.Wrap(err, "failed to execute contract")
}

// reset caller nonce
acc, err := accountutil.AccountState(ctx, sm, protocol.MustGetActionCtx(ctx).Caller)
if err != nil {
log.L().Panic("failed to get account state", zap.Error(err))
}
acc.DecreaseNonce()
if err := accountutil.StoreAccount(sm, protocol.MustGetActionCtx(ctx).Caller, acc); err != nil {
log.L().Panic("failed to store account", zap.Error(err))
}
return receipt, nil
}

// Validate validates an execution
func (p *Protocol) Validate(ctx context.Context, act action.Action, _ protocol.StateReader) error {
exec, ok := act.(*action.Execution)
Expand Down
26 changes: 14 additions & 12 deletions action/protocol/staking/handler_stake_migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ import (
"github.com/iotexproject/iotex-core/state"
)

func (p *Protocol) handleStakeMigrate(ctx context.Context, act *action.MigrateStake, csm CandidateStateManager) ([]*action.Log, []*action.TransactionLog, uint64, error) {
func (p *Protocol) handleStakeMigrate(ctx context.Context, act *action.MigrateStake, csm CandidateStateManager) ([]*action.Log, []*action.TransactionLog, uint64, bool, error) {
actLogs := make([]*action.Log, 0)
transferLogs := make([]*action.TransactionLog, 0)
nonceUpdated := false
si := csm.SM().Snapshot()
revertSM := func() {
if revertErr := csm.SM().Revert(si); revertErr != nil {
Expand All @@ -31,30 +32,30 @@ func (p *Protocol) handleStakeMigrate(ctx context.Context, act *action.MigrateSt
}
insGas, err := act.IntrinsicGas()
if err != nil {
return nil, nil, 0, err
return nil, nil, 0, nonceUpdated, err
}

// validate bucket index
bucket, rErr := p.fetchBucket(csm, act.BucketIndex())
if rErr != nil {
return nil, nil, 0, rErr
return nil, nil, 0, nonceUpdated, rErr
}
if err := p.validateStakeMigrate(ctx, bucket, csm); err != nil {
return nil, nil, 0, err
return nil, nil, 0, nonceUpdated, err
}

// force-withdraw native bucket
staker, rerr := fetchCaller(ctx, csm, big.NewInt(0))
if rerr != nil {
return nil, nil, 0, errors.Wrap(rerr, "failed to fetch caller")
return nil, nil, 0, nonceUpdated, errors.Wrap(rerr, "failed to fetch caller")
}
candidate := csm.GetByIdentifier(bucket.Candidate)
if candidate == nil {
return nil, nil, 0, errCandNotExist
return nil, nil, 0, nonceUpdated, errCandNotExist
}
actLog, tLog, err := p.withdrawBucket(ctx, staker, bucket, candidate, csm)
if err != nil {
return nil, nil, 0, err
return nil, nil, 0, nonceUpdated, err
}
actLogs = append(actLogs, actLog.Build(ctx, nil))
transferLogs = append(transferLogs, tLog)
Expand All @@ -64,21 +65,22 @@ func (p *Protocol) handleStakeMigrate(ctx context.Context, act *action.MigrateSt
exec, err := p.constructExecution(candidate.GetIdentifier(), bucket.StakedAmount, duration, act.Nonce(), act.GasLimit(), act.GasPrice())
if err != nil {
revertSM()
return nil, nil, 0, errors.Wrap(err, "failed to construct execution")
return nil, nil, 0, nonceUpdated, errors.Wrap(err, "failed to construct execution")
}
excReceipt, err := p.createNFTBucket(ctx, exec, csm.SM())
if err != nil {
revertSM()
return nil, nil, 0, errors.Wrap(err, "failed to handle execution action")
return nil, nil, 0, nonceUpdated, errors.Wrap(err, "failed to handle execution action")
}
nonceUpdated = true
if excReceipt.Status != uint64(iotextypes.ReceiptStatus_Success) {
revertSM()
return nil, nil, 0, errors.Errorf("execution failed with status %d", excReceipt.Status)
return nil, nil, 0, nonceUpdated, errors.Errorf("execution failed with status %d", excReceipt.Status)
}
// add sub-receipts logs
actLogs = append(actLogs, excReceipt.Logs()...)
transferLogs = append(transferLogs, excReceipt.TransactionLogs()...)
return actLogs, transferLogs, excReceipt.GasConsumed + insGas, nil
return actLogs, transferLogs, excReceipt.GasConsumed + insGas, nonceUpdated, nil
}

func (p *Protocol) validateStakeMigrate(ctx context.Context, bucket *VoteBucket, csm CandidateStateManager) error {
Expand Down Expand Up @@ -195,7 +197,7 @@ func (p *Protocol) createNFTBucket(ctx context.Context, exeAct *action.Execution
if exctPtl == nil {
return nil, errors.New("execution protocol is not registered")
}
excReceipt, err := exctPtl.HandleCrossProtocol(ctx, exeAct, sm)
excReceipt, err := exctPtl.Handle(ctx, exeAct, sm)
if err != nil {
return nil, errors.Wrap(err, "failed to handle execution action")
}
Expand Down
6 changes: 3 additions & 3 deletions action/protocol/staking/handler_stake_migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ func TestHandleStakeMigrate(t *testing.T) {
pa := NewPatches()
defer pa.Reset()
sm.EXPECT().Revert(gomock.Any()).Return(nil).AnyTimes()
pa.ApplyMethodReturn(excPrtl, "HandleCrossProtocol", &action.Receipt{
pa.ApplyMethodReturn(excPrtl, "Handle", &action.Receipt{
Status: uint64(iotextypes.ReceiptStatus_Failure),
}, nil)
receipts, errs := runBlock(ctx, p, sm, 8, timeBlock,
Expand All @@ -231,7 +231,7 @@ func TestHandleStakeMigrate(t *testing.T) {
t.Run("error from contract call", func(t *testing.T) {
pa := NewPatches()
defer pa.Reset()
pa.ApplyMethodFunc(excPrtl, "HandleCrossProtocol", func(ctx context.Context, act action.Action, sm protocol.StateManager) (*action.Receipt, error) {
pa.ApplyMethodFunc(excPrtl, "Handle", func(ctx context.Context, act action.Action, sm protocol.StateManager) (*action.Receipt, error) {
return nil, errors.New("execution failed error")
})
sm.EXPECT().Revert(gomock.Any()).Return(nil).AnyTimes()
Expand Down Expand Up @@ -275,7 +275,7 @@ func TestHandleStakeMigrate(t *testing.T) {
Type: iotextypes.TransactionLogType_IN_CONTRACT_TRANSFER,
Amount: big.NewInt(100),
})
pa.ApplyMethodReturn(excPrtl, "HandleCrossProtocol", receipt, nil)
pa.ApplyMethodReturn(excPrtl, "Handle", receipt, nil)
act := assertions.MustNoErrorV(action.SignedMigrateStake(popNonce(&stakerNonce), bktIdx, gasLimit, gasPrice, identityset.PrivateKey(stakerID)))
receipts, _ = runBlock(ctx, p, sm, 11, timeBlock,
act,
Expand Down
65 changes: 42 additions & 23 deletions action/protocol/staking/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,10 @@ func NewProtocol(

// new vote reviser, revise ate greenland
voteReviser := NewVoteReviser(cfg.Staking.VoteWeightCalConsts, correctCandsHeight, reviseHeights...)

migrateContractAddress := ""
if contractStakingIndexerV2 != nil {
migrateContractAddress = contractStakingIndexerV2.ContractAddress()
}
return &Protocol{
addr: addr,
config: Configuration{
Expand All @@ -170,6 +173,7 @@ func NewProtocol(
BootstrapCandidates: cfg.Staking.BootstrapCandidates,
PersistStakingPatchBlock: cfg.PersistStakingPatchBlock,
EndorsementWithdrawWaitingBlocks: cfg.Staking.EndorsementWithdrawWaitingBlocks,
MigrateContractAddress: migrateContractAddress,
},
candBucketsIndexer: candBucketsIndexer,
voteReviser: voteReviser,
Expand Down Expand Up @@ -415,12 +419,13 @@ func (p *Protocol) constructCandidateStateManager(ctx context.Context, sm protoc

func (p *Protocol) handle(ctx context.Context, act action.Action, csm CandidateStateManager) (*action.Receipt, error) {
var (
rLog *receiptLog
tLogs []*action.TransactionLog
err error
logs []*action.Log
actionCtx = protocol.MustGetActionCtx(ctx)
gasConsumed = actionCtx.IntrinsicGas
rLog *receiptLog
tLogs []*action.TransactionLog
err error
logs []*action.Log
nonceUpdateOption = updateNonce
actionCtx = protocol.MustGetActionCtx(ctx)
gasConsumed = actionCtx.IntrinsicGas
)

switch act := act.(type) {
Expand Down Expand Up @@ -449,7 +454,11 @@ func (p *Protocol) handle(ctx context.Context, act action.Action, csm CandidateS
case *action.CandidateTransferOwnership:
rLog, tLogs, err = p.handleCandidateTransferOwnership(ctx, act, csm)
case *action.MigrateStake:
logs, tLogs, gasConsumed, err = p.handleStakeMigrate(ctx, act, csm)
var nonceUpdated bool
logs, tLogs, gasConsumed, nonceUpdated, err = p.handleStakeMigrate(ctx, act, csm)
if nonceUpdated {
nonceUpdateOption = noUpdateNonce
}
default:
return nil, nil
}
Expand All @@ -459,14 +468,14 @@ func (p *Protocol) handle(ctx context.Context, act action.Action, csm CandidateS
}
}
if err == nil {
return p.settleAction(ctx, csm.SM(), uint64(iotextypes.ReceiptStatus_Success), logs, tLogs, gasConsumed)
return p.settleAction(ctx, csm.SM(), uint64(iotextypes.ReceiptStatus_Success), logs, tLogs, gasConsumed, nonceUpdateOption)
}

if receiptErr, ok := err.(ReceiptError); ok {
actionCtx := protocol.MustGetActionCtx(ctx)
log.L().With(
zap.String("actionHash", hex.EncodeToString(actionCtx.ActionHash[:]))).Debug("Failed to commit staking action", zap.Error(err))
return p.settleAction(ctx, csm.SM(), receiptErr.ReceiptStatus(), logs, tLogs, gasConsumed)
return p.settleAction(ctx, csm.SM(), receiptErr.ReceiptStatus(), logs, tLogs, gasConsumed, nonceUpdateOption)
}
return nil, err
}
Expand Down Expand Up @@ -677,6 +686,13 @@ func (p *Protocol) calculateVoteWeight(v *VoteBucket, selfStake bool) *big.Int {
return CalculateVoteWeight(p.config.VoteWeightCalConsts, v, selfStake)
}

type nonceUpdateType bool

const (
updateNonce nonceUpdateType = true
noUpdateNonce nonceUpdateType = false
)

// settleAction deposits gas fee and updates caller's nonce
func (p *Protocol) settleAction(
ctx context.Context,
Expand All @@ -685,6 +701,7 @@ func (p *Protocol) settleAction(
logs []*action.Log,
tLogs []*action.TransactionLog,
gasConsumed uint64,
updateNonce nonceUpdateType,
) (*action.Receipt, error) {
actionCtx := protocol.MustGetActionCtx(ctx)
blkCtx := protocol.MustGetBlockCtx(ctx)
Expand All @@ -693,19 +710,21 @@ func (p *Protocol) settleAction(
if err != nil {
return nil, errors.Wrap(err, "failed to deposit gas")
}
accountCreationOpts := []state.AccountCreationOption{}
if protocol.MustGetFeatureCtx(ctx).CreateLegacyNonceAccount {
accountCreationOpts = append(accountCreationOpts, state.LegacyNonceAccountTypeOption())
}
acc, err := accountutil.LoadAccount(sm, actionCtx.Caller, accountCreationOpts...)
if err != nil {
return nil, err
}
if err := acc.SetPendingNonce(actionCtx.Nonce + 1); err != nil {
return nil, errors.Wrap(err, "failed to set nonce")
}
if err := accountutil.StoreAccount(sm, actionCtx.Caller, acc); err != nil {
return nil, errors.Wrap(err, "failed to update nonce")
if updateNonce {
accountCreationOpts := []state.AccountCreationOption{}
if protocol.MustGetFeatureCtx(ctx).CreateLegacyNonceAccount {
accountCreationOpts = append(accountCreationOpts, state.LegacyNonceAccountTypeOption())
}
acc, err := accountutil.LoadAccount(sm, actionCtx.Caller, accountCreationOpts...)
if err != nil {
return nil, err
}
if err := acc.SetPendingNonce(actionCtx.Nonce + 1); err != nil {
return nil, errors.Wrap(err, "failed to set nonce")
}
if err := accountutil.StoreAccount(sm, actionCtx.Caller, acc); err != nil {
return nil, errors.Wrap(err, "failed to update nonce")
}
}
r := action.Receipt{
Status: status,
Expand Down
13 changes: 0 additions & 13 deletions state/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,19 +188,6 @@ func (st *Account) ConvertFreshAccountToZeroNonceType(nonce uint64) bool {
return false
}

// DecreaseNonce decrements the nonce of the account
func (st *Account) DecreaseNonce() {
switch st.accountType {
case 0, 1:
if st.nonce == 0 {
panic("nonce underflow")
}
st.nonce--
default:
panic(errors.Wrapf(ErrUnknownAccountType, "account type %d", st.accountType))
}
}

// PendingNonce returns the pending nonce of the account
func (st *Account) PendingNonce() uint64 {
switch st.accountType {
Expand Down

0 comments on commit e56a50a

Please sign in to comment.