/
account.go
211 lines (184 loc) · 4.83 KB
/
account.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
/*
* Copyright (c) 2018 QLC Chain Team
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
package types
import (
"encoding/hex"
"encoding/json"
"fmt"
"github.com/qlcchain/go-qlc/crypto/ed25519"
)
type Account struct {
pubKey ed25519.PublicKey
privKey ed25519.PrivateKey
}
//go:generate msgp
type TokenMeta struct {
//TokenAccount Address `msg:"tokenAccount,extension" json:"token_account"`
Type Hash `msg:"type,extension" json:"type"`
Header Hash `msg:"header,extension" json:"header"`
Representative Address `msg:"rep,extension" json:"representative"`
OpenBlock Hash `msg:"open,extension" json:"open"`
Balance Balance `msg:"balance,extension" json:"balance"`
BelongTo Address `msg:"account,extension" json:"account"`
Modified int64 `msg:"modified" json:"modified"`
BlockCount int64 `msg:"blockCount," json:"blockCount"`
}
//go:generate msgp
type AccountMeta struct {
Address Address `msg:"account,extension" json:"account"`
CoinBalance Balance `msg:"balance,extension" json:"balance"`
CoinVote Balance `msg:"vote,extension" json:"vote"`
CoinNetwork Balance `msg:"network,extension" json:"network"`
CoinStorage Balance `msg:"storage,extension" json:"storage"`
CoinOracle Balance `msg:"oracle,extension" json:"oracle"`
Tokens []*TokenMeta `msg:"tokens" json:"tokens"`
}
//Token get token meta by token type hash
func (am *AccountMeta) Token(tt Hash) *TokenMeta {
for _, token := range am.Tokens {
if token.Type == tt {
return token
}
}
return nil
}
func (a *AccountMeta) VoteWeight() Balance {
balance := ZeroBalance
if a.CoinBalance.Int != nil {
balance = balance.Add(a.CoinBalance)
}
if a.CoinVote.Int != nil {
balance = balance.Add(a.CoinVote)
}
if a.CoinNetwork.Int != nil {
balance = balance.Add(a.CoinNetwork)
}
return balance
}
func (a *AccountMeta) GetVote() Balance {
if a.CoinVote.Int == nil {
return ZeroBalance
}
return a.CoinVote
}
func (a *AccountMeta) GetOracle() Balance {
if a.CoinOracle.Int == nil {
return ZeroBalance
}
return a.CoinOracle
}
func (a *AccountMeta) GetNetwork() Balance {
if a.CoinNetwork.Int == nil {
return ZeroBalance
}
return a.CoinNetwork
}
func (a *AccountMeta) GetBalance() Balance {
if a.CoinBalance.Int == nil {
return ZeroBalance
}
return a.CoinBalance
}
func (a *AccountMeta) GetStorage() Balance {
if a.CoinStorage.Int == nil {
return ZeroBalance
}
return a.CoinStorage
}
func (a *AccountMeta) TotalBalance() Balance {
balance := ZeroBalance
if a.CoinBalance.Int != nil {
balance = balance.Add(a.CoinBalance)
}
if a.CoinVote.Int != nil {
balance = balance.Add(a.CoinVote)
}
if a.CoinStorage.Int != nil {
balance = balance.Add(a.CoinStorage)
}
if a.CoinNetwork.Int != nil {
balance = balance.Add(a.CoinNetwork)
}
if a.CoinOracle.Int != nil {
balance = balance.Add(a.CoinOracle)
}
return balance
}
func (am *AccountMeta) Serialize() ([]byte, error) {
return am.MarshalMsg(nil)
}
func (am *AccountMeta) Deserialize(text []byte) error {
_, err := am.UnmarshalMsg(text)
if err != nil {
return err
}
return nil
}
func (tm *TokenMeta) Serialize() ([]byte, error) {
return tm.MarshalMsg(nil)
}
func (tm *TokenMeta) Deserialize(text []byte) error {
_, err := tm.UnmarshalMsg(text)
if err != nil {
return err
}
return nil
}
func (tm *TokenMeta) Clone() *TokenMeta {
t := TokenMeta{}
bytes, _ := tm.Serialize()
_ = t.Deserialize(bytes)
return &t
}
func (am *AccountMeta) Clone() *AccountMeta {
clone := AccountMeta{}
clone.Address = am.Address
clone.CoinBalance = am.CoinBalance
clone.CoinNetwork = am.CoinNetwork
clone.CoinVote = am.CoinVote
clone.CoinOracle = am.CoinOracle
clone.CoinStorage = am.CoinStorage
for _, tm := range am.Tokens {
t := TokenMeta{}
bytes, _ := tm.MarshalMsg(nil)
t.UnmarshalMsg(bytes)
clone.Tokens = append(clone.Tokens, &t)
}
return &clone
}
func (am *AccountMeta) String() string {
bytes, _ := json.Marshal(am)
return string(bytes)
}
// NewAccount creates a new account with the given private key.
func NewAccount(key ed25519.PrivateKey) *Account {
return &Account{
pubKey: key.Public().(ed25519.PublicKey),
privKey: key,
}
}
// Address returns the public key of this account as an Address type.
func (a *Account) Address() Address {
var address Address
copy(address[:], a.pubKey)
return address
}
func (a *Account) PrivateKey() ed25519.PrivateKey {
return a.privKey
}
func (a *Account) Sign(hash Hash) Signature {
return a.SignData(hash[:])
}
func (a *Account) SignData(data []byte) Signature {
var sig Signature
copy(sig[:], ed25519.Sign(a.privKey, data))
return sig
}
// String implements the fmt.Stringer interface.
func (a *Account) String() string {
return fmt.Sprintf("Address: %s, Private key: %s", a.Address().String(), hex.EncodeToString(a.privKey))
}