Skip to content

Commit

Permalink
address comments
Browse files Browse the repository at this point in the history
  • Loading branch information
envestcc committed Jun 18, 2024
1 parent 0fda2c4 commit e81cb70
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 34 deletions.
46 changes: 24 additions & 22 deletions action/protocol/staking/handler_stake_migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,14 @@ func (p *Protocol) handleStakeMigrate(ctx context.Context, act *action.MigrateSt
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 {
log.L().Panic("failed to revert state", zap.Error(revertErr))
}
}
insGas, err := act.IntrinsicGas()
if err != nil {
return nil, nil, 0, nonceUpdated, err
}

// validate bucket index
bucket, rErr := p.fetchBucket(csm, act.BucketIndex())
if rErr != nil {
return nil, nil, 0, nonceUpdated, rErr
}
if err := p.validateStakeMigrate(ctx, bucket, csm); err != nil {
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, nonceUpdated, errors.Wrap(rerr, "failed to fetch caller")
Expand All @@ -53,20 +40,31 @@ func (p *Protocol) handleStakeMigrate(ctx context.Context, act *action.MigrateSt
if candidate == nil {
return nil, nil, 0, nonceUpdated, errCandNotExist
}
duration := uint64(bucket.StakedDuration / p.helperCtx.BlockInterval(protocol.MustGetBlockCtx(ctx).BlockHeight))
exec, err := p.constructExecution(candidate.GetIdentifier(), bucket.StakedAmount, duration, act.Nonce(), act.GasLimit(), act.GasPrice())
if err != nil {
return nil, nil, 0, nonceUpdated, errors.Wrap(err, "failed to construct execution")
}
// validate bucket index
if err := p.validateStakeMigrate(ctx, bucket, csm); err != nil {
return nil, nil, 0, nonceUpdated, err
}

// snapshot for sm in case of failure of hybrid protocol handling
si := csm.SM().Snapshot()
revertSM := func() {
if revertErr := csm.SM().Revert(si); revertErr != nil {
log.L().Panic("failed to revert state", zap.Error(revertErr))
}
}
// force-withdraw native bucket
actLog, tLog, err := p.withdrawBucket(ctx, staker, bucket, candidate, csm)
if err != nil {
return nil, nil, 0, nonceUpdated, err
}
actLogs = append(actLogs, actLog.Build(ctx, nil))
transferLogs = append(transferLogs, tLog)

// call staking contract to stake
duration := uint64(bucket.StakedDuration / p.helperCtx.BlockInterval(protocol.MustGetBlockCtx(ctx).BlockHeight))
exec, err := p.constructExecution(candidate.GetIdentifier(), bucket.StakedAmount, duration, act.Nonce(), act.GasLimit(), act.GasPrice())
if err != nil {
revertSM()
return nil, nil, 0, nonceUpdated, errors.Wrap(err, "failed to construct execution")
}
excReceipt, err := p.createNFTBucket(ctx, exec, csm.SM())
if err != nil {
revertSM()
Expand All @@ -75,12 +73,16 @@ func (p *Protocol) handleStakeMigrate(ctx context.Context, act *action.MigrateSt
nonceUpdated = true
if excReceipt.Status != uint64(iotextypes.ReceiptStatus_Success) {
revertSM()
return nil, nil, 0, nonceUpdated, errors.Errorf("execution failed with status %d", excReceipt.Status)
nonceUpdated = false
return excReceipt.Logs(), excReceipt.TransactionLogs(), excReceipt.GasConsumed + insGas, nonceUpdated, &handleError{
err: errors.Errorf("staking contract failure: %s", excReceipt.ExecutionRevertMsg()),
failureStatus: iotextypes.ReceiptStatus(excReceipt.Status),
}
}
// add sub-receipts logs
actLogs = append(actLogs, excReceipt.Logs()...)
transferLogs = append(transferLogs, excReceipt.TransactionLogs()...)
return actLogs, transferLogs, excReceipt.GasConsumed + insGas, nonceUpdated, nil
return actLogs, transferLogs, insGas, nonceUpdated, nil
}

func (p *Protocol) validateStakeMigrate(ctx context.Context, bucket *VoteBucket, csm CandidateStateManager) error {
Expand Down
50 changes: 38 additions & 12 deletions action/protocol/staking/handler_stake_migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,7 @@ func TestHandleStakeMigrate(t *testing.T) {
receipts := make([]*action.Receipt, 0)
errs := make([]error, 0)
for _, act := range acts {
// si := sm.Snapshot()
receipt, err := runAction(ctx, p, act, sm)
// if err != nil {
// r.NoError(sm.Revert(si))
// }
receipts = append(receipts, receipt)
errs = append(errs, err)
}
Expand Down Expand Up @@ -218,23 +214,53 @@ func TestHandleStakeMigrate(t *testing.T) {
t.Run("failure from contract call", func(t *testing.T) {
pa := NewPatches()
defer pa.Reset()
sm.EXPECT().Revert(gomock.Any()).Return(nil).AnyTimes()
pa.ApplyMethodReturn(excPrtl, "Handle", &action.Receipt{
Status: uint64(iotextypes.ReceiptStatus_Failure),
}, nil)
sm.EXPECT().Revert(gomock.Any()).Return(nil).Times(1)
receipt := &action.Receipt{
Status: uint64(iotextypes.ReceiptStatus_Failure),
GasConsumed: 1000000,
}
actLog := &action.Log{
Address: address.ZeroAddress,
Topics: action.Topics{
hash.BytesToHash256([]byte("withdraw")),
},
}
txLog := &action.TransactionLog{
Type: iotextypes.TransactionLogType_GAS_FEE,
Sender: "",
Recipient: "",
Amount: new(big.Int).Mul(new(big.Int).SetUint64(receipt.GasConsumed), gasPrice),
}
receipt.AddLogs(actLog)
receipt.AddTransactionLogs(txLog)
pa.ApplyMethodReturn(excPrtl, "Handle", receipt, nil)
act := assertions.MustNoErrorV(action.SignedMigrateStake(popNonce(&stakerNonce), 1, gasLimit, gasPrice, identityset.PrivateKey(stakerID)))
receipts, errs := runBlock(ctx, p, sm, 8, timeBlock,
assertions.MustNoErrorV(action.SignedMigrateStake(stakerNonce, 1, gasLimit, gasPrice, identityset.PrivateKey(stakerID))),
act,
)
r.Len(receipts, 1)
r.ErrorContains(errs[0], "execution failed with status")
r.NoError(errs[0])
h, err := act.Hash()
r.NoError(err)
expectReceipt := &action.Receipt{
Status: receipt.Status,
ActionHash: h,
BlockHeight: 8,
GasConsumed: receipt.GasConsumed + action.MigrateStakeBaseIntrinsicGas,
ContractAddress: address.StakingProtocolAddr,
TxIndex: uint32(0),
}
expectReceipt.AddLogs(actLog)
expectReceipt.AddTransactionLogs(txLog)
r.Equal(expectReceipt, receipts[0])
})
t.Run("error from contract call", func(t *testing.T) {
pa := NewPatches()
defer pa.Reset()
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()
sm.EXPECT().Revert(gomock.Any()).Return(nil).Times(1)
receipts, errs := runBlock(ctx, p, sm, 9, timeBlock,
assertions.MustNoErrorV(action.SignedCreateStake(popNonce(&stakerNonce), "cand1", stakeAmount.String(), stakeDurationDays, true, nil, gasLimit, gasPrice, identityset.PrivateKey(stakerID))),
assertions.MustNoErrorV(action.SignedMigrateStake(stakerNonce, 5, gasLimit, gasPrice, identityset.PrivateKey(stakerID))),
Expand Down Expand Up @@ -284,7 +310,7 @@ func TestHandleStakeMigrate(t *testing.T) {
r.Equal(uint64(iotextypes.ReceiptStatus_Success), receipts[0].Status)
// gas = instrinsic + contract call
instriGas, _ := act.IntrinsicGas()
r.Equal(receipt.GasConsumed+instriGas, receipts[0].GasConsumed)
r.Equal(instriGas, receipts[0].GasConsumed)
// withdraw log + stake log
r.Len(receipts[0].Logs(), 2)
r.Equal(&action.Log{
Expand Down

0 comments on commit e81cb70

Please sign in to comment.