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
|
// Copyright (C) 2019-2024 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// go-algorand is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
package ledgercore
import (
"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/crypto/merklesignature"
"github.com/algorand/go-algorand/data/basics"
)
// AccountData provides users of the Balances interface per-account data (like basics.AccountData)
// but without any maps containing AppParams, AppLocalState, AssetHolding, or AssetParams. This
// ensures that transaction evaluation must retrieve and mutate account, asset, and application data
// separately, to better support on-disk and in-memory schemas that do not store them together.
type AccountData struct {
AccountBaseData
VotingData
}
// AccountBaseData contains base account info like balance, status and total number of resources
type AccountBaseData struct {
Status basics.Status
MicroAlgos basics.MicroAlgos
RewardsBase uint64
RewardedMicroAlgos basics.MicroAlgos
AuthAddr basics.Address
TotalAppSchema basics.StateSchema // Totals across created globals, and opted in locals.
TotalExtraAppPages uint32 // Total number of extra pages across all created apps
TotalAppParams uint64 // Total number of apps this account has created
TotalAppLocalStates uint64 // Total number of apps this account is opted into.
TotalAssetParams uint64 // Total number of assets created by this account
TotalAssets uint64 // Total of asset creations and optins (i.e. number of holdings)
TotalBoxes uint64 // Total number of boxes associated to this account
TotalBoxBytes uint64 // Total bytes for this account's boxes. keys _and_ values count
}
// VotingData holds participation information
type VotingData struct {
VoteID crypto.OneTimeSignatureVerifier
SelectionID crypto.VRFVerifier
StateProofID merklesignature.Commitment
VoteFirstValid basics.Round
VoteLastValid basics.Round
VoteKeyDilution uint64
}
// OnlineAccountData holds MicroAlgosWithRewards and VotingData as needed for agreement
type OnlineAccountData struct {
MicroAlgosWithRewards basics.MicroAlgos
VotingData
}
// ToAccountData returns ledgercore.AccountData from basics.AccountData
func ToAccountData(acct basics.AccountData) AccountData {
return AccountData{
AccountBaseData: AccountBaseData{
Status: acct.Status,
MicroAlgos: acct.MicroAlgos,
RewardsBase: acct.RewardsBase,
RewardedMicroAlgos: acct.RewardedMicroAlgos,
AuthAddr: acct.AuthAddr,
TotalAppSchema: acct.TotalAppSchema,
TotalExtraAppPages: acct.TotalExtraAppPages,
TotalAssetParams: uint64(len(acct.AssetParams)),
TotalAssets: uint64(len(acct.Assets)),
TotalAppParams: uint64(len(acct.AppParams)),
TotalAppLocalStates: uint64(len(acct.AppLocalStates)),
TotalBoxes: acct.TotalBoxes,
TotalBoxBytes: acct.TotalBoxBytes,
},
VotingData: VotingData{
VoteID: acct.VoteID,
SelectionID: acct.SelectionID,
StateProofID: acct.StateProofID,
VoteFirstValid: acct.VoteFirstValid,
VoteLastValid: acct.VoteLastValid,
VoteKeyDilution: acct.VoteKeyDilution,
},
}
}
// AssignAccountData assigns the contents of AccountData to the fields in basics.AccountData,
// but does not touch the AppParams, AppLocalState, AssetHolding, or AssetParams data.
func AssignAccountData(a *basics.AccountData, acct AccountData) {
a.Status = acct.Status
a.MicroAlgos = acct.MicroAlgos
a.RewardsBase = acct.RewardsBase
a.RewardedMicroAlgos = acct.RewardedMicroAlgos
a.VoteID = acct.VoteID
a.SelectionID = acct.SelectionID
a.StateProofID = acct.StateProofID
a.VoteFirstValid = acct.VoteFirstValid
a.VoteLastValid = acct.VoteLastValid
a.VoteKeyDilution = acct.VoteKeyDilution
a.AuthAddr = acct.AuthAddr
a.TotalAppSchema = acct.TotalAppSchema
a.TotalExtraAppPages = acct.TotalExtraAppPages
a.TotalBoxes = acct.TotalBoxes
a.TotalBoxBytes = acct.TotalBoxBytes
}
// WithUpdatedRewards calls basics account data WithUpdatedRewards
func (u AccountData) WithUpdatedRewards(proto config.ConsensusParams, rewardsLevel uint64) AccountData {
u.MicroAlgos, u.RewardedMicroAlgos, u.RewardsBase = basics.WithUpdatedRewards(
proto, u.Status, u.MicroAlgos, u.RewardedMicroAlgos, u.RewardsBase, rewardsLevel,
)
return u
}
// ClearOnlineState resets the account's fields to indicate that the account is an offline account
func (u *AccountData) ClearOnlineState() {
u.Status = basics.Offline
u.VotingData = VotingData{}
}
// MinBalance computes the minimum balance requirements for an account based on
// some consensus parameters. MinBalance should correspond roughly to how much
// storage the account is allowed to store on disk.
func (u AccountData) MinBalance(proto *config.ConsensusParams) (res basics.MicroAlgos) {
return basics.MinBalance(
proto,
uint64(u.TotalAssets),
u.TotalAppSchema,
uint64(u.TotalAppParams), uint64(u.TotalAppLocalStates),
uint64(u.TotalExtraAppPages),
u.TotalBoxes, u.TotalBoxBytes,
)
}
// IsZero checks if an AccountData value is the same as its zero value.
func (u AccountData) IsZero() bool {
return u == AccountData{}
}
// Money is similar to basics account data Money function
func (u AccountData) Money(proto config.ConsensusParams, rewardsLevel uint64) (money basics.MicroAlgos, rewards basics.MicroAlgos) {
e := u.WithUpdatedRewards(proto, rewardsLevel)
return e.MicroAlgos, e.RewardedMicroAlgos
}
// OnlineAccountData calculates the online account data given an AccountData, by adding the rewards.
func (u AccountData) OnlineAccountData(proto config.ConsensusParams, rewardsLevel uint64) OnlineAccountData {
if u.Status != basics.Online {
// if the account is not Online and agreement requests it for some reason, clear it out
return OnlineAccountData{}
}
microAlgos, _, _ := basics.WithUpdatedRewards(
proto, u.Status, u.MicroAlgos, u.RewardedMicroAlgos, u.RewardsBase, rewardsLevel,
)
return OnlineAccountData{
MicroAlgosWithRewards: microAlgos,
VotingData: VotingData{
VoteID: u.VoteID,
SelectionID: u.SelectionID,
StateProofID: u.StateProofID,
VoteFirstValid: u.VoteFirstValid,
VoteLastValid: u.VoteLastValid,
VoteKeyDilution: u.VoteKeyDilution,
},
}
}
// NormalizedOnlineBalance wraps basics.NormalizedOnlineAccountBalance
func (u *AccountData) NormalizedOnlineBalance(genesisProto config.ConsensusParams) uint64 {
return basics.NormalizedOnlineAccountBalance(u.Status, u.RewardsBase, u.MicroAlgos, genesisProto)
}
|