/
state.go
246 lines (204 loc) · 9.69 KB
/
state.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// Copyright 2019 DxChain, All rights reserved.
// Use of this source code is governed by an Apache
// License 2.0 that can be found in the LICENSE file.
package dpos
import (
"encoding/binary"
"math/big"
"github.com/DxChainNetwork/godx/common"
"github.com/DxChainNetwork/godx/core/types"
)
type stateDB interface {
GetState(addr common.Address, key common.Hash) common.Hash
SetState(addr common.Address, key, value common.Hash)
ForEachStorage(addr common.Address, cb func(common.Hash, common.Hash) bool) error
Exist(addr common.Address) bool
CreateAccount(addr common.Address)
GetNonce(common.Address) uint64
SetNonce(addr common.Address, nonce uint64)
GetBalance(addr common.Address) *big.Int
}
var (
// KeyVoteDeposit is the key of vote deposit
KeyVoteDeposit = common.BytesToHash([]byte("vote-deposit"))
// KeyCandidateDeposit is the key of candidates deposit
KeyCandidateDeposit = common.BytesToHash([]byte("candidates-deposit"))
// KeyRewardRatioNumerator is the key of block reward ration numerator indicates the percent of share validator with its delegators
KeyRewardRatioNumerator = common.BytesToHash([]byte("reward-ratio-numerator"))
// KeyRewardRatioNumeratorLastEpoch is the key for storing the reward ratio in
// the last epoch.
KeyRewardRatioNumeratorLastEpoch = common.BytesToHash([]byte("reward-ratio-last-epoch"))
// KeyVoteLastEpoch is the vote deposit in the last epoch
KeyVoteLastEpoch = common.BytesToHash([]byte("vote-last-epoch"))
// KeyTotalVote is the key of total vote for each candidates
KeyTotalVote = common.BytesToHash([]byte("total-vote"))
// KeyFrozenAssets is the key for frozen assets for in an account
KeyFrozenAssets = common.BytesToHash([]byte("frozen-assets"))
// PrefixThawingAssets is the prefix recording the amount to be thawed in a specified epoch
PrefixThawingAssets = []byte("thawing-assets")
// KeyPreEpochSnapshotDelegateTrieRoot is the key of block number where snapshot delegate trie
KeyPreEpochSnapshotDelegateTrieRoot = common.BytesToHash([]byte("pre-epoch-dtr"))
// KeyValueCommonAddress is the address for some common key-value storage
KeyValueCommonAddress = common.BigToAddress(big.NewInt(0))
// KeySumAllocatedReward is the key of sum allocated block reward until now
KeySumAllocatedReward = common.BytesToHash([]byte("sum-allocated-reward"))
)
// GetCandidateDeposit get the candidates deposit of the addr from the state
func GetCandidateDeposit(state stateDB, addr common.Address) common.BigInt {
depositHash := state.GetState(addr, KeyCandidateDeposit)
return common.PtrBigInt(depositHash.Big())
}
// SetCandidateDeposit set the candidates deposit of the addr in the state
func SetCandidateDeposit(state stateDB, addr common.Address, deposit common.BigInt) {
hash := common.BigToHash(deposit.BigIntPtr())
state.SetState(addr, KeyCandidateDeposit, hash)
}
// GetVoteDeposit get the vote deposit of the addr from the state
func GetVoteDeposit(state stateDB, addr common.Address) common.BigInt {
depositHash := state.GetState(addr, KeyVoteDeposit)
return common.PtrBigInt(depositHash.Big())
}
// SetVoteDeposit set the vote deposit of the addr in the state
func SetVoteDeposit(state stateDB, addr common.Address, deposit common.BigInt) {
hash := common.BigToHash(deposit.BigIntPtr())
state.SetState(addr, KeyVoteDeposit, hash)
}
// GetRewardRatioNumerator get the reward ratio for a candidates for the addr in state.
// The value is used in calculating block reward for miner and his delegator
func GetRewardRatioNumerator(state stateDB, addr common.Address) uint64 {
rewardRatioHash := state.GetState(addr, KeyRewardRatioNumerator)
return hashToUint64(rewardRatioHash)
}
// SetRewardRatioNumerator set the CandidateRewardRatioNumerator for the addr
// in state
func SetRewardRatioNumerator(state stateDB, addr common.Address, value uint64) {
hash := uint64ToHash(value)
state.SetState(addr, KeyRewardRatioNumerator, hash)
}
// GetRewardRatioNumeratorLastEpoch get the rewardRatio for the validator in the last epoch
func GetRewardRatioNumeratorLastEpoch(state stateDB, addr common.Address) uint64 {
hash := state.GetState(addr, KeyRewardRatioNumeratorLastEpoch)
return hashToUint64(hash)
}
// SetRewardRatioNumeratorLastEpoch set the rewardRatio for the validator in the last epoch
func SetRewardRatioNumeratorLastEpoch(state stateDB, addr common.Address, value uint64) {
hash := uint64ToHash(value)
state.SetState(addr, KeyRewardRatioNumeratorLastEpoch, hash)
}
// GetFrozenAssets returns the frozen assets for an addr
func GetFrozenAssets(state stateDB, addr common.Address) common.BigInt {
hash := state.GetState(addr, KeyFrozenAssets)
return common.PtrBigInt(hash.Big())
}
// SetFrozenAssets set the frozen assets for an addr
func SetFrozenAssets(state stateDB, addr common.Address, value common.BigInt) {
hash := common.BigToHash(value.BigIntPtr())
state.SetState(addr, KeyFrozenAssets, hash)
}
// AddFrozenAssets add the diff to the frozen assets of the address
func AddFrozenAssets(state stateDB, addr common.Address, diff common.BigInt) {
prev := GetFrozenAssets(state, addr)
newValue := prev.Add(diff)
SetFrozenAssets(state, addr, newValue)
}
// SubFrozenAssets sub the diff from the frozen assets of the address
func SubFrozenAssets(state stateDB, addr common.Address, diff common.BigInt) error {
prev := GetFrozenAssets(state, addr)
if prev.Cmp(diff) < 0 {
return errInsufficientFrozenAssets
}
newValue := prev.Sub(diff)
SetFrozenAssets(state, addr, newValue)
return nil
}
// GetBalance returns the balance of the address. This is simply an adapter function
// to convert the type from *big.Int to common.BigInt
func GetBalance(state stateDB, addr common.Address) common.BigInt {
balance := state.GetBalance(addr)
return common.PtrBigInt(balance)
}
// GetAvailableBalance get the available balance, which is the result of balance minus
// frozen assets.
func GetAvailableBalance(state stateDB, addr common.Address) common.BigInt {
balance := GetBalance(state, addr)
frozenAssets := GetFrozenAssets(state, addr)
return balance.Sub(frozenAssets)
}
// GetThawingAssets return the thawing asset amount of the address in a certain epoch
func GetThawingAssets(state stateDB, addr common.Address, epoch int64) common.BigInt {
key := makeThawingAssetsKey(epoch)
hash := state.GetState(addr, key)
return common.PtrBigInt(hash.Big())
}
// SetThawingAssets set the thawing assets in the epoch field for the addr in state
func SetThawingAssets(state stateDB, addr common.Address, epoch int64, value common.BigInt) {
key := makeThawingAssetsKey(epoch)
hash := common.BigToHash(value.BigIntPtr())
state.SetState(addr, key, hash)
}
// AddThawingAssets add the thawing assets of diff in the epoch field for the addr in state
func AddThawingAssets(state stateDB, addr common.Address, epoch int64, diff common.BigInt) {
prev := GetThawingAssets(state, addr, epoch)
newValue := prev.Add(diff)
SetThawingAssets(state, addr, epoch, newValue)
}
// removeThawingAssets remove the thawing assets in a certain epoch for the address
func removeThawingAssets(state stateDB, addr common.Address, epoch int64) {
key := makeThawingAssetsKey(epoch)
state.SetState(addr, key, common.Hash{})
}
// makeThawingAssetsKey makes the key for the thawing assets in a certain epoch
func makeThawingAssetsKey(epoch int64) common.Hash {
epochByte := make([]byte, 8)
binary.BigEndian.PutUint64(epochByte, uint64(epoch))
return common.BytesToHash(append(PrefixThawingAssets, epochByte...))
}
// GetVoteLastEpoch get the vote deposit in the last epoch
func GetVoteLastEpoch(state stateDB, addr common.Address) common.BigInt {
h := state.GetState(addr, KeyVoteLastEpoch)
return common.PtrBigInt(h.Big())
}
// SetVoteLastEpoch set the vote epoch in the last epoch
func SetVoteLastEpoch(state stateDB, addr common.Address, value common.BigInt) {
h := common.BigToHash(value.BigIntPtr())
state.SetState(addr, KeyVoteLastEpoch, h)
}
// removeAddressInState remove the address from the state. Note currently only set nonce to 0.
// The balance field is not checked thus there is no guarantee that the account is removed.
// If this is the case, simply leave the address there.
func removeAddressInState(state stateDB, addr common.Address) {
state.SetNonce(addr, 0)
}
// GetPreEpochSnapshotDelegateTrieRoot get the block number of snapshot delegate trie
func GetPreEpochSnapshotDelegateTrieRoot(state stateDB, genesis *types.Header) common.Hash {
h := state.GetState(KeyValueCommonAddress, KeyPreEpochSnapshotDelegateTrieRoot)
if h == types.EmptyHash {
h = genesis.DposContext.DelegateRoot
}
return h
}
// setPreEpochSnapshotDelegateTrieRoot set the block number of snapshot delegate trie
func setPreEpochSnapshotDelegateTrieRoot(state stateDB, value common.Hash) {
state.SetNonce(KeyValueCommonAddress, state.GetNonce(KeyValueCommonAddress)+1)
state.SetState(KeyValueCommonAddress, KeyPreEpochSnapshotDelegateTrieRoot, value)
}
// setSumAllocatedReward set the sum allocated block reward until now
func setSumAllocatedReward(state stateDB, value common.BigInt) {
if !state.Exist(KeyValueCommonAddress) {
state.CreateAccount(KeyValueCommonAddress)
}
state.SetNonce(KeyValueCommonAddress, state.GetNonce(KeyValueCommonAddress)+1)
hash := common.BigToHash(value.BigIntPtr())
state.SetState(KeyValueCommonAddress, KeySumAllocatedReward, hash)
}
// getSumAllocatedReward get the sum allocated block reward until now
func getSumAllocatedReward(state stateDB) common.BigInt {
sumAllocatedRewardHash := state.GetState(KeyValueCommonAddress, KeySumAllocatedReward)
return common.PtrBigInt(sumAllocatedRewardHash.Big())
}
// addSumAllocatedReward add diff to the sum allocated block reward
func addSumAllocatedReward(state stateDB, diff common.BigInt) {
prevSum := getSumAllocatedReward(state)
newSum := prevSum.Add(diff)
setSumAllocatedReward(state, newSum)
}