-
Notifications
You must be signed in to change notification settings - Fork 179
/
account.go
133 lines (121 loc) · 3.11 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
// (c) 2019 Dapper Labs - ALL RIGHTS RESERVED
package flow
import (
"encoding/json"
"fmt"
"github.com/onflow/flow-go/crypto"
"github.com/onflow/flow-go/crypto/hash"
)
// Account represents an account on the Flow network.
//
// An account can be an externally owned account or a contract account with code.
type Account struct {
Address Address
Balance uint64
Keys []AccountPublicKey
Contracts map[string][]byte
}
// AccountPublicKey is a public key associated with an account.
//
// An account public key contains the public key, signing and hashing algorithms, and a key weight.
type AccountPublicKey struct {
Index int
PublicKey crypto.PublicKey
SignAlgo crypto.SigningAlgorithm
HashAlgo hash.HashingAlgorithm
SeqNumber uint64
Weight int
Revoked bool
}
func (a AccountPublicKey) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
PublicKey []byte
SignAlgo crypto.SigningAlgorithm
HashAlgo hash.HashingAlgorithm
SeqNumber uint64
Weight int
}{
a.PublicKey.Encode(),
a.SignAlgo,
a.HashAlgo,
a.SeqNumber,
a.Weight,
})
}
func (a *AccountPublicKey) UnmarshalJSON(data []byte) error {
temp := struct {
PublicKey []byte
SignAlgo crypto.SigningAlgorithm
HashAlgo hash.HashingAlgorithm
SeqNumber uint64
Weight int
}{}
err := json.Unmarshal(data, &temp)
if err != nil {
return err
}
if a == nil {
a = new(AccountPublicKey)
}
a.PublicKey, err = crypto.DecodePublicKey(temp.SignAlgo, temp.PublicKey)
if err != nil {
return err
}
a.SignAlgo = temp.SignAlgo
a.HashAlgo = temp.HashAlgo
a.SeqNumber = temp.SeqNumber
a.Weight = temp.Weight
return nil
}
// Validate returns an error if this account key is invalid.
//
// An account key can be invalid for the following reasons:
// - It specifies an incompatible signature/hash algorithm pairing
// - (TODO) It specifies a negative key weight
func (a AccountPublicKey) Validate() error {
if !CompatibleAlgorithms(a.SignAlgo, a.HashAlgo) {
return fmt.Errorf(
"signing algorithm (%s) is incompatible with hashing algorithm (%s)",
a.SignAlgo,
a.HashAlgo,
)
}
return nil
}
// AccountPrivateKey is a private key associated with an account.
type AccountPrivateKey struct {
PrivateKey crypto.PrivateKey
SignAlgo crypto.SigningAlgorithm
HashAlgo hash.HashingAlgorithm
}
// PublicKey returns a weighted public key.
func (a AccountPrivateKey) PublicKey(weight int) AccountPublicKey {
return AccountPublicKey{
PublicKey: a.PrivateKey.PublicKey(),
SignAlgo: a.SignAlgo,
HashAlgo: a.HashAlgo,
Weight: weight,
}
}
func (a AccountPrivateKey) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
PrivateKey []byte
SignAlgo crypto.SigningAlgorithm
HashAlgo hash.HashingAlgorithm
}{
a.PrivateKey.Encode(),
a.SignAlgo,
a.HashAlgo,
})
}
// CompatibleAlgorithms returns true if the signature and hash algorithms are compatible.
func CompatibleAlgorithms(sigAlgo crypto.SigningAlgorithm, hashAlgo hash.HashingAlgorithm) bool {
switch sigAlgo {
case crypto.ECDSAP256, crypto.ECDSASecp256k1:
switch hashAlgo {
case hash.SHA2_256, hash.SHA3_256:
return true
}
}
return false
}