Skip to content

Commit 9be4cb0

Browse files
authored
add staking action amount into implicit transfer log (iotexproject#2282)
1 parent 5dc9202 commit 9be4cb0

File tree

8 files changed

+371
-107
lines changed

8 files changed

+371
-107
lines changed

action/protocol/rewarding/protocol_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ func testProtocol(t *testing.T, test func(*testing.T, context.Context, protocol.
4141
sm := mock_chainmanager.NewMockStateManager(ctrl)
4242
cb := batch.NewCachedBatch()
4343

44+
// action.RewardingProtocolID is defined to avoid import cycle, make sure they match
45+
require.Equal(t, protocolID, action.RewardingProtocolID)
46+
4447
sm.EXPECT().State(gomock.Any(), gomock.Any()).DoAndReturn(
4548
func(account interface{}, opts ...protocol.StateOption) (uint64, error) {
4649
cfg, err := protocol.CreateStateConfig(opts...)

action/protocol/staking/handlers.go

+97-37
Original file line numberDiff line numberDiff line change
@@ -62,56 +62,71 @@ func (h *handleError) ReceiptStatus() uint64 {
6262
}
6363

6464
func (p *Protocol) handleCreateStake(ctx context.Context, act *action.CreateStake, csm CandidateStateManager,
65-
) (*receiptLog, error) {
65+
) (*receiptLog, *action.Log, error) {
6666
actionCtx := protocol.MustGetActionCtx(ctx)
6767
blkCtx := protocol.MustGetBlockCtx(ctx)
6868
log := newReceiptLog(p.addr.String(), HandleCreateStake, blkCtx.BlockHeight >= p.hu.FbkMigrationBlockHeight())
6969

7070
staker, fetchErr := fetchCaller(ctx, csm, act.Amount())
7171
if fetchErr != nil {
72-
return log, fetchErr
72+
return log, nil, fetchErr
7373
}
7474

7575
// Create new bucket and bucket index
7676
candidate := csm.GetByName(act.Candidate())
7777
if candidate == nil {
78-
return log, errCandNotExist
78+
return log, nil, errCandNotExist
7979
}
8080
bucket := NewVoteBucket(candidate.Owner, actionCtx.Caller, act.Amount(), act.Duration(), blkCtx.BlockTimeStamp, act.AutoStake())
8181
bucketIdx, err := putBucketAndIndex(csm, bucket)
8282
if err != nil {
83-
return log, err
83+
return log, nil, err
8484
}
8585
log.AddTopics(byteutil.Uint64ToBytesBigEndian(bucketIdx), candidate.Owner.Bytes())
8686

8787
// update candidate
8888
weightedVote := p.calculateVoteWeight(bucket, false)
8989
if err := candidate.AddVote(weightedVote); err != nil {
90-
return log, &handleError{
90+
return log, nil, &handleError{
9191
err: errors.Wrapf(err, "failed to add vote for candidate %s", candidate.Owner.String()),
9292
failureStatus: iotextypes.ReceiptStatus_ErrInvalidBucketAmount,
9393
}
9494
}
9595
if err := csm.Upsert(candidate); err != nil {
96-
return log, csmErrorToHandleError(candidate.Owner.String(), err)
96+
return log, nil, csmErrorToHandleError(candidate.Owner.String(), err)
9797
}
9898

9999
// update staker balance
100100
if err := staker.SubBalance(act.Amount()); err != nil {
101-
return log, &handleError{
101+
return log, nil, &handleError{
102102
err: errors.Wrapf(err, "failed to update the balance of staker %s", actionCtx.Caller.String()),
103103
failureStatus: iotextypes.ReceiptStatus_ErrNotEnoughBalance,
104104
}
105105
}
106106
// put updated staker's account state to trie
107107
if err := accountutil.StoreAccount(csm, actionCtx.Caller, staker); err != nil {
108-
return log, errors.Wrapf(err, "failed to store account %s", actionCtx.Caller.String())
108+
return log, nil, errors.Wrapf(err, "failed to store account %s", actionCtx.Caller.String())
109109
}
110110

111111
log.AddAddress(candidate.Owner)
112112
log.AddAddress(actionCtx.Caller)
113113
log.SetData(byteutil.Uint64ToBytesBigEndian(bucketIdx))
114-
return log, nil
114+
115+
// generate create amount log
116+
cLog := action.Log{
117+
Address: p.addr.String(),
118+
Topics: action.Topics{
119+
action.BucketCreateAmount,
120+
hash.BytesToHash256(actionCtx.Caller.Bytes()),
121+
hash.BytesToHash256(p.addr.Bytes()),
122+
hash.BytesToHash256(byteutil.Uint64ToBytesBigEndian(bucket.Index)),
123+
},
124+
Data: act.Amount().Bytes(),
125+
BlockHeight: blkCtx.BlockHeight,
126+
ActionHash: actionCtx.ActionHash,
127+
Index: 1,
128+
}
129+
return log, &cLog, nil
115130
}
116131

117132
func (p *Protocol) handleUnstake(ctx context.Context, act *action.Unstake, csm CandidateStateManager,
@@ -239,8 +254,9 @@ func (p *Protocol) handleWithdrawStake(ctx context.Context, act *action.Withdraw
239254
Address: p.addr.String(),
240255
Topics: action.Topics{
241256
action.BucketWithdrawAmount,
242-
hash.BytesToHash256(byteutil.Uint64ToBytesBigEndian(bucket.Index)),
257+
hash.BytesToHash256(p.addr.Bytes()),
243258
hash.BytesToHash256(actionCtx.Caller.Bytes()),
259+
hash.BytesToHash256(byteutil.Uint64ToBytesBigEndian(bucket.Index)),
244260
},
245261
Data: bucket.StakedAmount.Bytes(),
246262
BlockHeight: blkCtx.BlockHeight,
@@ -391,79 +407,93 @@ func (p *Protocol) handleConsignmentTransfer(
391407
}
392408

393409
func (p *Protocol) handleDepositToStake(ctx context.Context, act *action.DepositToStake, csm CandidateStateManager,
394-
) (*receiptLog, error) {
410+
) (*receiptLog, *action.Log, error) {
395411
actionCtx := protocol.MustGetActionCtx(ctx)
396412
blkCtx := protocol.MustGetBlockCtx(ctx)
397413
log := newReceiptLog(p.addr.String(), HandleDepositToStake, blkCtx.BlockHeight >= p.hu.FbkMigrationBlockHeight())
398414

399415
depositor, fetchErr := fetchCaller(ctx, csm, act.Amount())
400416
if fetchErr != nil {
401-
return log, fetchErr
417+
return log, nil, fetchErr
402418
}
403419

404420
bucket, fetchErr := p.fetchBucket(csm, actionCtx.Caller, act.BucketIndex(), false, true)
405421
if fetchErr != nil {
406-
return log, fetchErr
422+
return log, nil, fetchErr
407423
}
408424
log.AddTopics(byteutil.Uint64ToBytesBigEndian(bucket.Index), bucket.Owner.Bytes(), bucket.Candidate.Bytes())
409425
if !bucket.AutoStake {
410-
return log, &handleError{
426+
return log, nil, &handleError{
411427
err: errors.New("deposit is only allowed on auto-stake bucket"),
412428
failureStatus: iotextypes.ReceiptStatus_ErrInvalidBucketType,
413429
}
414430
}
415431
candidate := csm.GetByOwner(bucket.Candidate)
416432
if candidate == nil {
417-
return log, errCandNotExist
433+
return log, nil, errCandNotExist
418434
}
419435

420436
prevWeightedVotes := p.calculateVoteWeight(bucket, csm.ContainsSelfStakingBucket(act.BucketIndex()))
421437
// update bucket
422438
bucket.StakedAmount.Add(bucket.StakedAmount, act.Amount())
423439
if err := updateBucket(csm, act.BucketIndex(), bucket); err != nil {
424-
return log, errors.Wrapf(err, "failed to update bucket for voter %s", bucket.Owner.String())
440+
return log, nil, errors.Wrapf(err, "failed to update bucket for voter %s", bucket.Owner.String())
425441
}
426442

427443
// update candidate
428444
if err := candidate.SubVote(prevWeightedVotes); err != nil {
429-
return log, &handleError{
445+
return log, nil, &handleError{
430446
err: errors.Wrapf(err, "failed to subtract vote for candidate %s", bucket.Candidate.String()),
431447
failureStatus: iotextypes.ReceiptStatus_ErrNotEnoughBalance,
432448
}
433449
}
434450
weightedVotes := p.calculateVoteWeight(bucket, csm.ContainsSelfStakingBucket(act.BucketIndex()))
435451
if err := candidate.AddVote(weightedVotes); err != nil {
436-
return log, &handleError{
452+
return log, nil, &handleError{
437453
err: errors.Wrapf(err, "failed to add vote for candidate %s", candidate.Owner.String()),
438454
failureStatus: iotextypes.ReceiptStatus_ErrInvalidBucketAmount,
439455
}
440456
}
441457
if csm.ContainsSelfStakingBucket(act.BucketIndex()) {
442458
if err := candidate.AddSelfStake(act.Amount()); err != nil {
443-
return log, &handleError{
459+
return log, nil, &handleError{
444460
err: errors.Wrapf(err, "failed to add self stake for candidate %s", candidate.Owner.String()),
445461
failureStatus: iotextypes.ReceiptStatus_ErrInvalidBucketAmount,
446462
}
447463
}
448464
}
449465
if err := csm.Upsert(candidate); err != nil {
450-
return log, csmErrorToHandleError(candidate.Owner.String(), err)
466+
return log, nil, csmErrorToHandleError(candidate.Owner.String(), err)
451467
}
452468

453469
// update depositor balance
454470
if err := depositor.SubBalance(act.Amount()); err != nil {
455-
return log, &handleError{
471+
return log, nil, &handleError{
456472
err: errors.Wrapf(err, "failed to update the balance of depositor %s", actionCtx.Caller.String()),
457473
failureStatus: iotextypes.ReceiptStatus_ErrNotEnoughBalance,
458474
}
459475
}
460476
// put updated depositor's account state to trie
461477
if err := accountutil.StoreAccount(csm, actionCtx.Caller, depositor); err != nil {
462-
return log, errors.Wrapf(err, "failed to store account %s", actionCtx.Caller.String())
478+
return log, nil, errors.Wrapf(err, "failed to store account %s", actionCtx.Caller.String())
463479
}
464-
465480
log.AddAddress(actionCtx.Caller)
466-
return log, nil
481+
482+
// generate deposit amount log
483+
dLog := action.Log{
484+
Address: p.addr.String(),
485+
Topics: action.Topics{
486+
action.BucketDepositAmount,
487+
hash.BytesToHash256(actionCtx.Caller.Bytes()),
488+
hash.BytesToHash256(p.addr.Bytes()),
489+
hash.BytesToHash256(byteutil.Uint64ToBytesBigEndian(bucket.Index)),
490+
},
491+
Data: act.Amount().Bytes(),
492+
BlockHeight: blkCtx.BlockHeight,
493+
ActionHash: actionCtx.ActionHash,
494+
Index: 1,
495+
}
496+
return log, &dLog, nil
467497
}
468498

469499
func (p *Protocol) handleRestake(ctx context.Context, act *action.Restake, csm CandidateStateManager,
@@ -537,7 +567,7 @@ func (p *Protocol) handleRestake(ctx context.Context, act *action.Restake, csm C
537567
}
538568

539569
func (p *Protocol) handleCandidateRegister(ctx context.Context, act *action.CandidateRegister, csm CandidateStateManager,
540-
) (*receiptLog, error) {
570+
) (*receiptLog, *action.Log, *action.Log, error) {
541571
actCtx := protocol.MustGetActionCtx(ctx)
542572
blkCtx := protocol.MustGetBlockCtx(ctx)
543573
log := newReceiptLog(p.addr.String(), HandleCandidateRegister, blkCtx.BlockHeight >= p.hu.FbkMigrationBlockHeight())
@@ -546,7 +576,7 @@ func (p *Protocol) handleCandidateRegister(ctx context.Context, act *action.Cand
546576

547577
caller, fetchErr := fetchCaller(ctx, csm, new(big.Int).Add(act.Amount(), registrationFee))
548578
if fetchErr != nil {
549-
return log, fetchErr
579+
return log, nil, nil, fetchErr
550580
}
551581

552582
owner := actCtx.Caller
@@ -558,22 +588,22 @@ func (p *Protocol) handleCandidateRegister(ctx context.Context, act *action.Cand
558588
ownerExist := c != nil
559589
// cannot collide with existing owner (with selfstake != 0)
560590
if ownerExist && c.SelfStake.Cmp(big.NewInt(0)) != 0 {
561-
return log, &handleError{
591+
return log, nil, nil, &handleError{
562592
err: ErrInvalidOwner,
563593
failureStatus: iotextypes.ReceiptStatus_ErrCandidateAlreadyExist,
564594
}
565595
}
566596
// cannot collide with existing name
567597
if csm.ContainsName(act.Name()) && (!ownerExist || act.Name() != c.Name) {
568-
return log, &handleError{
598+
return log, nil, nil, &handleError{
569599
err: ErrInvalidCanName,
570600
failureStatus: iotextypes.ReceiptStatus_ErrCandidateConflict,
571601
}
572602
}
573603
// cannot collide with existing operator address
574604
if csm.ContainsOperator(act.OperatorAddress()) &&
575605
(!ownerExist || !address.Equal(act.OperatorAddress(), c.Operator)) {
576-
return log, &handleError{
606+
return log, nil, nil, &handleError{
577607
err: ErrInvalidOperator,
578608
failureStatus: iotextypes.ReceiptStatus_ErrCandidateConflict,
579609
}
@@ -582,7 +612,7 @@ func (p *Protocol) handleCandidateRegister(ctx context.Context, act *action.Cand
582612
bucket := NewVoteBucket(owner, owner, act.Amount(), act.Duration(), blkCtx.BlockTimeStamp, act.AutoStake())
583613
bucketIdx, err := putBucketAndIndex(csm, bucket)
584614
if err != nil {
585-
return log, err
615+
return log, nil, nil, err
586616
}
587617
log.AddTopics(byteutil.Uint64ToBytesBigEndian(bucketIdx), owner.Bytes())
588618

@@ -597,30 +627,61 @@ func (p *Protocol) handleCandidateRegister(ctx context.Context, act *action.Cand
597627
}
598628

599629
if err := csm.Upsert(c); err != nil {
600-
return log, csmErrorToHandleError(owner.String(), err)
630+
return log, nil, nil, csmErrorToHandleError(owner.String(), err)
601631
}
602632

603633
// update caller balance
604634
if err := caller.SubBalance(act.Amount()); err != nil {
605-
return log, &handleError{
635+
return log, nil, nil, &handleError{
606636
err: errors.Wrapf(err, "failed to update the balance of register %s", actCtx.Caller.String()),
607637
failureStatus: iotextypes.ReceiptStatus_ErrNotEnoughBalance,
608638
}
609639
}
610640
// put updated caller's account state to trie
611641
if err := accountutil.StoreAccount(csm, actCtx.Caller, caller); err != nil {
612-
return log, errors.Wrapf(err, "failed to store account %s", actCtx.Caller.String())
642+
return log, nil, nil, errors.Wrapf(err, "failed to store account %s", actCtx.Caller.String())
613643
}
614644

615645
// put registrationFee to reward pool
616646
if err := p.depositGas(ctx, csm, registrationFee); err != nil {
617-
return log, errors.Wrap(err, "failed to deposit gas")
647+
return log, nil, nil, errors.Wrap(err, "failed to deposit gas")
618648
}
619649

620650
log.AddAddress(owner)
621651
log.AddAddress(actCtx.Caller)
622652
log.SetData(byteutil.Uint64ToBytesBigEndian(bucketIdx))
623-
return log, nil
653+
654+
// generate self-stake log
655+
cLog := action.Log{
656+
Address: p.addr.String(),
657+
Topics: action.Topics{
658+
action.CandidateSelfStake,
659+
hash.BytesToHash256(actCtx.Caller.Bytes()),
660+
hash.BytesToHash256(p.addr.Bytes()),
661+
hash.BytesToHash256(byteutil.Uint64ToBytesBigEndian(bucket.Index)),
662+
},
663+
Data: act.Amount().Bytes(),
664+
BlockHeight: blkCtx.BlockHeight,
665+
ActionHash: actCtx.ActionHash,
666+
Index: 1,
667+
}
668+
669+
// generate candidate register log
670+
rewardingAddr := hash.Hash160b([]byte(action.RewardingProtocolID))
671+
rLog := action.Log{
672+
Address: p.addr.String(),
673+
Topics: action.Topics{
674+
action.CandidateRegistrationFee,
675+
hash.BytesToHash256(actCtx.Caller.Bytes()),
676+
hash.BytesToHash256(rewardingAddr[:]),
677+
hash.BytesToHash256(byteutil.Uint64ToBytesBigEndian(bucket.Index)),
678+
},
679+
Data: registrationFee.Bytes(),
680+
BlockHeight: blkCtx.BlockHeight,
681+
ActionHash: actCtx.ActionHash,
682+
Index: 2,
683+
}
684+
return log, &cLog, &rLog, nil
624685
}
625686

626687
func (p *Protocol) handleCandidateUpdate(ctx context.Context, act *action.CandidateUpdate, csm CandidateStateManager,
@@ -791,8 +852,7 @@ func BucketIndexFromReceiptLog(log *iotextypes.Log) (uint64, bool) {
791852
case hash.BytesToHash256([]byte(HandleCreateStake)), hash.BytesToHash256([]byte(HandleUnstake)),
792853
hash.BytesToHash256([]byte(HandleWithdrawStake)), hash.BytesToHash256([]byte(HandleChangeCandidate)),
793854
hash.BytesToHash256([]byte(HandleTransferStake)), hash.BytesToHash256([]byte(HandleDepositToStake)),
794-
hash.BytesToHash256([]byte(HandleRestake)), hash.BytesToHash256([]byte(HandleCandidateRegister)),
795-
action.BucketWithdrawAmount:
855+
hash.BytesToHash256([]byte(HandleRestake)), hash.BytesToHash256([]byte(HandleCandidateRegister)):
796856
return byteutil.BytesToUint64BigEndian(log.Topics[1][24:]), true
797857
default:
798858
return 0, false

0 commit comments

Comments
 (0)