github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/model/flow/account.go (about) 1 package flow 2 3 import ( 4 "encoding/json" 5 "fmt" 6 7 "github.com/onflow/crypto" 8 "github.com/onflow/crypto/hash" 9 ) 10 11 // Account represents an account on the Flow network. 12 // 13 // An account can be an externally owned account or a contract account with code. 14 type Account struct { 15 Address Address 16 Balance uint64 17 Keys []AccountPublicKey 18 Contracts map[string][]byte 19 } 20 21 // AccountPublicKey is a public key associated with an account. 22 // 23 // An account public key contains the public key, signing and hashing algorithms, and a key weight. 24 type AccountPublicKey struct { 25 Index int 26 PublicKey crypto.PublicKey 27 SignAlgo crypto.SigningAlgorithm 28 HashAlgo hash.HashingAlgorithm 29 SeqNumber uint64 30 Weight int 31 Revoked bool 32 } 33 34 func (a AccountPublicKey) MarshalJSON() ([]byte, error) { 35 return json.Marshal(struct { 36 PublicKey []byte 37 SignAlgo crypto.SigningAlgorithm 38 HashAlgo hash.HashingAlgorithm 39 SeqNumber uint64 40 Weight int 41 }{ 42 a.PublicKey.Encode(), 43 a.SignAlgo, 44 a.HashAlgo, 45 a.SeqNumber, 46 a.Weight, 47 }) 48 } 49 50 func (a *AccountPublicKey) UnmarshalJSON(data []byte) error { 51 temp := struct { 52 PublicKey []byte 53 SignAlgo crypto.SigningAlgorithm 54 HashAlgo hash.HashingAlgorithm 55 SeqNumber uint64 56 Weight int 57 }{} 58 err := json.Unmarshal(data, &temp) 59 if err != nil { 60 return err 61 } 62 if a == nil { 63 a = new(AccountPublicKey) 64 } 65 a.PublicKey, err = crypto.DecodePublicKey(temp.SignAlgo, temp.PublicKey) 66 if err != nil { 67 return err 68 } 69 a.SignAlgo = temp.SignAlgo 70 a.HashAlgo = temp.HashAlgo 71 a.SeqNumber = temp.SeqNumber 72 a.Weight = temp.Weight 73 return nil 74 } 75 76 // Validate returns an error if this account key is invalid. 77 // 78 // An account key can be invalid for the following reasons: 79 // - It specifies an incompatible signature/hash algorithm pairing 80 // - (TODO) It specifies a negative key weight 81 func (a AccountPublicKey) Validate() error { 82 if !CompatibleAlgorithms(a.SignAlgo, a.HashAlgo) { 83 return fmt.Errorf( 84 "signing algorithm (%s) is incompatible with hashing algorithm (%s)", 85 a.SignAlgo, 86 a.HashAlgo, 87 ) 88 } 89 return nil 90 } 91 92 // AccountPrivateKey is a private key associated with an account. 93 type AccountPrivateKey struct { 94 PrivateKey crypto.PrivateKey 95 SignAlgo crypto.SigningAlgorithm 96 HashAlgo hash.HashingAlgorithm 97 } 98 99 // PublicKey returns a weighted public key. 100 func (a AccountPrivateKey) PublicKey(weight int) AccountPublicKey { 101 return AccountPublicKey{ 102 PublicKey: a.PrivateKey.PublicKey(), 103 SignAlgo: a.SignAlgo, 104 HashAlgo: a.HashAlgo, 105 Weight: weight, 106 } 107 } 108 109 func (a AccountPrivateKey) MarshalJSON() ([]byte, error) { 110 return json.Marshal(struct { 111 PrivateKey []byte 112 SignAlgo crypto.SigningAlgorithm 113 HashAlgo hash.HashingAlgorithm 114 }{ 115 a.PrivateKey.Encode(), 116 a.SignAlgo, 117 a.HashAlgo, 118 }) 119 } 120 121 // CompatibleAlgorithms returns true if the signature and hash algorithms are compatible. 122 func CompatibleAlgorithms(sigAlgo crypto.SigningAlgorithm, hashAlgo hash.HashingAlgorithm) bool { 123 switch sigAlgo { 124 case crypto.ECDSAP256, crypto.ECDSASecp256k1: 125 switch hashAlgo { 126 case hash.SHA2_256, hash.SHA3_256: 127 return true 128 } 129 } 130 return false 131 }