github.com/koko1123/flow-go-1@v0.29.6/model/flow/account_encoder.go (about) 1 package flow 2 3 // TODO: these functions will be moved to a separate `encoding` package in a future PR 4 5 import ( 6 "github.com/ethereum/go-ethereum/rlp" 7 8 "github.com/onflow/cadence" 9 10 "github.com/onflow/flow-go/crypto" 11 "github.com/onflow/flow-go/crypto/hash" 12 ) 13 14 // accountPublicKeyWrapper is used for encoding and decoding. 15 type accountPublicKeyWrapper struct { 16 PublicKey []byte 17 SignAlgo uint 18 HashAlgo uint 19 Weight uint 20 SeqNumber uint64 21 Revoked bool 22 } 23 24 // legacyAccountPublicKeyWrapper is an RLP wrapper for the old public key format that does 25 // not contain a Revoked field. 26 type legacyAccountPublicKeyWrapper struct { 27 PublicKey []byte 28 SignAlgo uint 29 HashAlgo uint 30 Weight uint 31 SeqNumber uint64 32 } 33 34 // runtimeAccountPublicKeyWrapper must match format used in Transaction 35 // currently should match SDK AccountKey encoded format 36 type runtimeAccountPublicKeyWrapper struct { 37 PublicKey []byte 38 SignAlgo uint 39 HashAlgo uint 40 Weight uint 41 } 42 43 // accountPrivateKeyWrapper is used for encoding and decoding. 44 type accountPrivateKeyWrapper struct { 45 PrivateKey []byte 46 SignAlgo uint 47 HashAlgo uint 48 } 49 50 func EncodeAccountPublicKey(a AccountPublicKey) ([]byte, error) { 51 w := accountPublicKeyWrapper{ 52 PublicKey: a.PublicKey.Encode(), 53 SignAlgo: uint(a.SignAlgo), 54 HashAlgo: uint(a.HashAlgo), 55 Weight: uint(a.Weight), 56 SeqNumber: a.SeqNumber, 57 Revoked: a.Revoked, 58 } 59 60 return rlp.EncodeToBytes(&w) 61 } 62 63 func EncodeRuntimeAccountPublicKeys(keys []AccountPublicKey) ([]cadence.Value, error) { 64 encodedKeys := make([]cadence.Value, len(keys)) 65 for i, key := range keys { 66 k, err := EncodeRuntimeAccountPublicKey(key) 67 if err != nil { 68 return nil, err 69 } 70 71 values := make([]cadence.Value, len(k)) 72 for j, v := range k { 73 values[j] = cadence.NewUInt8(v) 74 } 75 encodedKeys[i] = cadence.NewArray(values) 76 } 77 78 return encodedKeys, nil 79 } 80 81 func EncodeRuntimeAccountPublicKey(a AccountPublicKey) ([]byte, error) { 82 publicKey := a.PublicKey.Encode() 83 84 w := runtimeAccountPublicKeyWrapper{ 85 PublicKey: publicKey, 86 SignAlgo: uint(a.SignAlgo), 87 HashAlgo: uint(a.HashAlgo), 88 Weight: uint(a.Weight), 89 } 90 91 return rlp.EncodeToBytes(&w) 92 } 93 94 func decodeAccountPublicKeyWrapper(b []byte) (accountPublicKeyWrapper, error) { 95 var wrapper accountPublicKeyWrapper 96 97 err := rlp.DecodeBytes(b, &wrapper) 98 if err != nil { 99 // public key data may be stored in legacy format, so convert 100 var legacyWrapper legacyAccountPublicKeyWrapper 101 102 err := rlp.DecodeBytes(b, &legacyWrapper) 103 if err != nil { 104 return accountPublicKeyWrapper{}, err 105 } 106 107 return accountPublicKeyWrapper{ 108 PublicKey: legacyWrapper.PublicKey, 109 SignAlgo: legacyWrapper.SignAlgo, 110 HashAlgo: legacyWrapper.HashAlgo, 111 Weight: legacyWrapper.Weight, 112 SeqNumber: legacyWrapper.SeqNumber, 113 Revoked: false, // all legacy keys are not revoked 114 }, nil 115 } 116 117 return wrapper, nil 118 } 119 120 func DecodeAccountPublicKey(b []byte, index uint64) (AccountPublicKey, error) { 121 w, err := decodeAccountPublicKeyWrapper(b) 122 if err != nil { 123 return AccountPublicKey{}, err 124 } 125 126 signAlgo := crypto.SigningAlgorithm(w.SignAlgo) 127 hashAlgo := hash.HashingAlgorithm(w.HashAlgo) 128 129 publicKey, err := crypto.DecodePublicKey(signAlgo, w.PublicKey) 130 if err != nil { 131 return AccountPublicKey{}, err 132 } 133 134 return AccountPublicKey{ 135 Index: int(index), 136 PublicKey: publicKey, 137 SignAlgo: signAlgo, 138 HashAlgo: hashAlgo, 139 Weight: int(w.Weight), 140 SeqNumber: w.SeqNumber, 141 Revoked: w.Revoked, 142 }, nil 143 } 144 145 // DecodeRuntimeAccountPublicKey decode bytes into AccountPublicKey 146 // but it is designed to accept byte-format used by Cadence runtime 147 // (currently same as SDK, but we don't want to keep explicit dependency 148 // on SDK) 149 func DecodeRuntimeAccountPublicKey(b []byte, seqNumber uint64) (AccountPublicKey, error) { 150 var w runtimeAccountPublicKeyWrapper 151 152 err := rlp.DecodeBytes(b, &w) 153 if err != nil { 154 return AccountPublicKey{}, err 155 } 156 157 signAlgo := crypto.SigningAlgorithm(w.SignAlgo) 158 hashAlgo := hash.HashingAlgorithm(w.HashAlgo) 159 160 publicKey, err := crypto.DecodePublicKey(signAlgo, w.PublicKey) 161 if err != nil { 162 return AccountPublicKey{}, err 163 } 164 165 return AccountPublicKey{ 166 PublicKey: publicKey, 167 SignAlgo: signAlgo, 168 HashAlgo: hashAlgo, 169 Weight: int(w.Weight), 170 SeqNumber: seqNumber, 171 }, nil 172 } 173 174 func EncodeAccountPrivateKey(a AccountPrivateKey) ([]byte, error) { 175 privateKey := a.PrivateKey.Encode() 176 177 w := accountPrivateKeyWrapper{ 178 PrivateKey: privateKey, 179 SignAlgo: uint(a.SignAlgo), 180 HashAlgo: uint(a.HashAlgo), 181 } 182 183 return rlp.EncodeToBytes(&w) 184 } 185 186 func DecodeAccountPrivateKey(b []byte) (AccountPrivateKey, error) { 187 var w accountPrivateKeyWrapper 188 189 err := rlp.DecodeBytes(b, &w) 190 if err != nil { 191 return AccountPrivateKey{}, err 192 } 193 194 signAlgo := crypto.SigningAlgorithm(w.SignAlgo) 195 hashAlgo := hash.HashingAlgorithm(w.HashAlgo) 196 197 privateKey, err := crypto.DecodePrivateKey(signAlgo, w.PrivateKey) 198 if err != nil { 199 return AccountPrivateKey{}, err 200 } 201 202 return AccountPrivateKey{ 203 PrivateKey: privateKey, 204 SignAlgo: signAlgo, 205 HashAlgo: hashAlgo, 206 }, nil 207 }