-
Notifications
You must be signed in to change notification settings - Fork 199
/
process.go
125 lines (103 loc) · 3.1 KB
/
process.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package rewardTransaction
import (
"math/big"
"github.com/ElrondNetwork/elrond-go-core/core"
"github.com/ElrondNetwork/elrond-go-core/core/check"
"github.com/ElrondNetwork/elrond-go-core/data/rewardTx"
"github.com/ElrondNetwork/elrond-go/process"
"github.com/ElrondNetwork/elrond-go/sharding"
"github.com/ElrondNetwork/elrond-go/state"
)
var _ process.RewardTransactionProcessor = (*rewardTxProcessor)(nil)
const rewardKey = "reward"
type rewardTxProcessor struct {
accounts state.AccountsAdapter
pubkeyConv core.PubkeyConverter
shardCoordinator sharding.Coordinator
}
// NewRewardTxProcessor creates a rewardTxProcessor instance
func NewRewardTxProcessor(
accountsDB state.AccountsAdapter,
pubkeyConv core.PubkeyConverter,
coordinator sharding.Coordinator,
) (*rewardTxProcessor, error) {
if check.IfNil(accountsDB) {
return nil, process.ErrNilAccountsAdapter
}
if check.IfNil(pubkeyConv) {
return nil, process.ErrNilPubkeyConverter
}
if check.IfNil(coordinator) {
return nil, process.ErrNilShardCoordinator
}
return &rewardTxProcessor{
accounts: accountsDB,
pubkeyConv: pubkeyConv,
shardCoordinator: coordinator,
}, nil
}
func (rtp *rewardTxProcessor) getAccountFromAddress(address []byte) (state.UserAccountHandler, error) {
shardForCurrentNode := rtp.shardCoordinator.SelfId()
shardForAddr := rtp.shardCoordinator.ComputeId(address)
if shardForCurrentNode != shardForAddr {
return nil, nil
}
acnt, err := rtp.accounts.LoadAccount(address)
if err != nil {
return nil, err
}
userAcnt, ok := acnt.(state.UserAccountHandler)
if !ok {
return nil, process.ErrWrongTypeAssertion
}
return userAcnt, nil
}
// ProcessRewardTransaction updates the account state from the reward transaction
func (rtp *rewardTxProcessor) ProcessRewardTransaction(rTx *rewardTx.RewardTx) error {
if rTx == nil {
return process.ErrNilRewardTransaction
}
if rTx.Value == nil {
return process.ErrNilValueFromRewardTransaction
}
accHandler, err := rtp.getAccountFromAddress(rTx.RcvAddr)
if err != nil {
return err
}
if check.IfNil(accHandler) {
// address from different shard
return nil
}
process.DisplayProcessTxDetails(
"ProcessRewardTransaction: receiver account details",
accHandler,
rTx,
rtp.pubkeyConv,
)
err = accHandler.AddToBalance(rTx.Value)
if err != nil {
return err
}
rtp.saveAccumulatedRewards(rTx, accHandler)
return rtp.accounts.SaveAccount(accHandler)
}
func (rtp *rewardTxProcessor) saveAccumulatedRewards(
rtx *rewardTx.RewardTx,
userAccount state.UserAccountHandler,
) {
if !core.IsSmartContractAddress(rtx.RcvAddr) {
return
}
existingReward := big.NewInt(0)
fullRewardKey := core.ElrondProtectedKeyPrefix + rewardKey
val, err := userAccount.DataTrieTracker().RetrieveValue([]byte(fullRewardKey))
if err == nil {
existingReward.SetBytes(val)
}
existingReward.Add(existingReward, rtx.Value)
_ = userAccount.DataTrieTracker().SaveKeyValue([]byte(fullRewardKey), existingReward.Bytes())
}
// IsInterfaceNil returns true if there is no value under the interface
func (rtp *rewardTxProcessor) IsInterfaceNil() bool {
return rtp == nil
}