github.com/onflow/flow-go@v0.33.17/model/flow/address.go (about) 1 // (c) 2019 Dapper Labs - ALL RIGHTS RESERVED 2 3 package flow 4 5 import ( 6 "encoding/binary" 7 "encoding/hex" 8 "fmt" 9 "strings" 10 ) 11 12 // AddressLength is the size of an account address in bytes. 13 // (n) is the size of an account address in bits. 14 const AddressLength = (linearCodeN + 7) >> 3 15 16 // Address represents the 8 byte address of an account. 17 type Address [AddressLength]byte 18 19 // EmptyAddress is the default value of a variable of type Address 20 var EmptyAddress = BytesToAddress(nil) 21 22 func ConvertAddress(b [AddressLength]byte) Address { 23 return Address(b) 24 } 25 26 // HexToAddress converts a hex string to an Address. 27 func HexToAddress(h string) Address { 28 trimmed := strings.TrimPrefix(h, "0x") 29 if len(trimmed)%2 == 1 { 30 trimmed = "0" + trimmed 31 } 32 b, _ := hex.DecodeString(trimmed) 33 return BytesToAddress(b) 34 } 35 36 // BytesToAddress returns Address with value b. 37 // 38 // If b is larger than 8, b will be cropped from the left. 39 // If b is smaller than 8, b will be appended by zeroes at the front. 40 func BytesToAddress(b []byte) Address { 41 var a Address 42 if len(b) > AddressLength { 43 b = b[len(b)-AddressLength:] 44 } 45 copy(a[AddressLength-len(b):], b) 46 return a 47 } 48 49 // Bytes returns the byte representation of the address. 50 func (a Address) Bytes() []byte { 51 return a[:] 52 } 53 54 // Hex returns the hex string representation of the address. 55 func (a Address) Hex() string { 56 return hex.EncodeToString(a.Bytes()) 57 } 58 59 // HexWithPrefix returns the hex string representation of the address, 60 // including the 0x prefix. 61 func (a Address) HexWithPrefix() string { 62 return "0x" + a.Hex() 63 } 64 65 // String returns the string representation of the address. 66 func (a Address) String() string { 67 return a.Hex() 68 } 69 70 // Short returns the string representation of the address with leading zeros 71 // removed. 72 func (a Address) Short() string { 73 hex := a.String() 74 trimmed := strings.TrimLeft(hex, "0") 75 if len(trimmed)%2 != 0 { 76 trimmed = "0" + trimmed 77 } 78 return trimmed 79 } 80 81 func (a Address) MarshalJSON() ([]byte, error) { 82 return []byte(fmt.Sprintf("\"%s\"", a.Hex())), nil 83 } 84 85 func (a *Address) UnmarshalJSON(data []byte) error { 86 *a = HexToAddress(strings.Trim(string(data), "\"")) 87 return nil 88 } 89 90 // uint64 converts an address into a uint64 91 func (a Address) uint64() uint64 { 92 v := binary.BigEndian.Uint64(a[:]) 93 return v 94 } 95 96 // modified from binary.bigEndian.uint64 97 func uint48(b []byte) uint64 { 98 _ = b[5] // bounds check hint to compiler; 99 return uint64(b[5]) | uint64(b[4])<<8 | 100 uint64(b[3])<<16 | uint64(b[2])<<24 | uint64(b[1])<<32 | uint64(b[0])<<40 101 } 102 103 // modified from binary.bigEndian.PutUint64 104 func putUint48(b []byte, v uint64) { 105 _ = b[5] // early bounds check to guarantee safety of writes below 106 b[0] = byte(v >> 40) 107 b[1] = byte(v >> 32) 108 b[2] = byte(v >> 24) 109 b[3] = byte(v >> 16) 110 b[4] = byte(v >> 8) 111 b[5] = byte(v) 112 } 113 114 // addressIndexLength is the size of an account address state in bytes. 115 // (k) is the size of an account address in bits. 116 const addressIndexLength = (linearCodeK + 7) >> 3 117 118 func indexToBytes(index uint64) []byte { 119 indexBytes := make([]byte, addressIndexLength) 120 putUint48(indexBytes, index) 121 return indexBytes 122 } 123 124 type AddressGenerator interface { 125 NextAddress() (Address, error) 126 CurrentAddress() Address 127 Bytes() []byte 128 AddressCount() uint64 // returns the total number of addresses that have been generated so far 129 } 130 131 type MonotonicAddressGenerator struct { 132 index uint64 133 } 134 135 // linearCodeAddressGenerator represents the internal index of the linear code address generation mechanism 136 type linearCodeAddressGenerator struct { 137 chainCodeWord uint64 138 index uint64 139 } 140 141 // Bytes converts an address index into a slice of bytes 142 func (gen *MonotonicAddressGenerator) Bytes() []byte { 143 return indexToBytes(gen.index) 144 } 145 146 // Bytes converts an address index into a slice of bytes 147 func (gen *linearCodeAddressGenerator) Bytes() []byte { 148 return indexToBytes(gen.index) 149 } 150 151 // NextAddress increments the internal index and generates the new address 152 // corresponding to the new index. 153 func (gen *MonotonicAddressGenerator) NextAddress() (Address, error) { 154 gen.index++ 155 if uint64(gen.index) > maxIndex { 156 return EmptyAddress, fmt.Errorf("the new index value is not valid, it must be less or equal to %x", maxIndex) 157 } 158 return gen.CurrentAddress(), nil 159 } 160 161 // CurrentAddress returns the address corresponding to the internal index. 162 func (gen *MonotonicAddressGenerator) CurrentAddress() Address { 163 return uint64ToAddress(gen.index) 164 } 165 166 // AddressCount returns the total number of addresses generated so far 167 func (gen *MonotonicAddressGenerator) AddressCount() uint64 { 168 return gen.index 169 } 170 171 // NextAddress generates an account address from the addressing index. 172 // 173 // The address is generated for a specific network (Flow mainnet, testnet..) 174 // The second returned value is the new updated addressing index. The new 175 // addressing index should replace the old index to keep generating account 176 // addresses in a sequential way. 177 // Each index is mapped to exactly one address. There are as many addresses 178 // as indices. 179 // zeroAddress() corresponds to the index "0" while ServiceAddress() corresponds to the 180 // index "1". 181 func (gen *linearCodeAddressGenerator) NextAddress() (Address, error) { 182 err := gen.nextIndex() 183 if err != nil { 184 return EmptyAddress, err 185 } 186 index := gen.index 187 address := encodeWord(index) 188 // customize the code word for a specific network 189 address ^= gen.chainCodeWord 190 return uint64ToAddress(address), nil 191 } 192 193 // CurrentAddress returns the current account address. 194 // 195 // The returned address is the address of the latest created account. 196 func (gen *linearCodeAddressGenerator) CurrentAddress() Address { 197 index := gen.index 198 address := encodeWord(index) 199 // customize the code word for a specific network 200 address ^= gen.chainCodeWord 201 return uint64ToAddress(address) 202 } 203 204 // AddressCount returns the total number of addresses generated so far 205 func (gen *linearCodeAddressGenerator) AddressCount() uint64 { 206 return gen.index 207 } 208 209 // increments the internal index of the generator. 210 // 211 // In this implemntation, the index values are simply 212 // incremented from 0 to 2^k-1. 213 func (gen *linearCodeAddressGenerator) nextIndex() error { 214 gen.index++ 215 if uint64(gen.index) > maxIndex { 216 return fmt.Errorf("the new index value is not valid, it must be less or equal to %x", maxIndex) 217 } 218 return nil 219 } 220 221 // uint64ToAddress returns an address with value v. 222 // 223 // The value v fits into the address as the address size is 8 224 func uint64ToAddress(v uint64) Address { 225 var b [AddressLength]byte 226 binary.BigEndian.PutUint64(b[:], v) 227 return Address(b) 228 } 229 230 const ( 231 // [n,k,d]-Linear code parameters 232 // The linear code used in the account addressing is a [64,45,7] 233 // It generates a [64,45]-code, which is the space of Flow account addresses. 234 // 235 // n is the size of the code words in bits, 236 // which is also the size of the account addresses in bits. 237 linearCodeN = 64 238 // k is size of the words in bits. 239 // 2^k is the total number of possible account addresses. 240 linearCodeK = 45 241 // p is the number of code parity bits. 242 // p = n - k 243 // 244 // d is the distance of the linear code. 245 // It is the minimum hamming distance between any two Flow account addresses. 246 // This means any pair of Flow addresses have at least 7 different bits, which 247 // minimizes the mistakes of typing wrong addresses. 248 // d is also the minimum hamming weight of all account addresses (the zero address is not an account address). 249 linearCodeD = 7 250 251 // the maximum value of the internal state, 2^k - 1. 252 maxIndex = (1 << linearCodeK) - 1 253 ) 254 255 // The following are invalid code-words in the [64,45] code. 256 // These constants are used to generate non-Flow-Mainnet addresses 257 258 // invalidCodeTestNetwork is the invalid codeword used for long-lived test networks. 259 const invalidCodeTestNetwork = uint64(0x6834ba37b3980209) 260 261 // invalidCodeTransientNetwork is the invalid codeword used for transient test networks. 262 const invalidCodeTransientNetwork = uint64(0x1cb159857af02018) 263 264 // invalidCodeSandboxNetwork is the invalid codeword used for Sandbox network. 265 const invalidCodeSandboxNetwork = uint64(0x1035ce4eff92ae01) 266 267 // encodeWord encodes a word into a code word. 268 // In Flow, the word is the account index while the code word 269 // is the corresponding address. 270 // 271 // The function assumes the word is valid (<2^k) 272 func encodeWord(word uint64) uint64 { 273 // Multiply the index GF(2) vector by the code generator matrix 274 codeWord := uint64(0) 275 for i := 0; i < linearCodeK; i++ { 276 if word&1 == 1 { 277 codeWord ^= generatorMatrixRows[i] 278 } 279 word >>= 1 280 } 281 return codeWord 282 } 283 284 // checks if the input is a valid code word of the linear code 285 func isValidCodeWord(codeWord uint64) bool { 286 // Multiply the code word GF(2)-vector by the parity-check matrix 287 parity := uint(0) 288 for i := 0; i < linearCodeN; i++ { 289 if codeWord&1 == 1 { 290 parity ^= parityCheckMatrixColumns[i] 291 } 292 codeWord >>= 1 293 } 294 return parity == 0 295 } 296 297 // reverse the linear code assuming the input is a valid 298 // codeWord. 299 func decodeCodeWord(codeWord uint64) uint64 { 300 // truncate the address GF(2) vector (last K bits) and multiply it by the inverse matrix of 301 // the partial code generator. 302 word := uint64(0) 303 codeWord >>= (linearCodeN - linearCodeK) 304 for i := 0; i < linearCodeK; i++ { 305 if codeWord&1 == 1 { 306 word ^= inverseMatrixRows[i] 307 } 308 codeWord >>= 1 309 } 310 return word 311 } 312 313 // Rows of the generator matrix G of the [64,45]-code used for Flow addresses. 314 // G is a (k x n) matrix with coefficients in GF(2), each row is converted into 315 // a big endian integer representation of the GF(2) raw vector. 316 // G is used to generate the account addresses 317 var generatorMatrixRows = [linearCodeK]uint64{ 318 0xe467b9dd11fa00df, 0xf233dcee88fe0abe, 0xf919ee77447b7497, 0xfc8cf73ba23a260d, 319 0xfe467b9dd11ee2a1, 0xff233dcee888d807, 0xff919ee774476ce6, 0x7fc8cf73ba231d10, 320 0x3fe467b9dd11b183, 0x1ff233dcee8f96d6, 0x8ff919ee774757ba, 0x47fc8cf73ba2b331, 321 0x23fe467b9dd27f6c, 0x11ff233dceee8e82, 0x88ff919ee775dd8f, 0x447fc8cf73b905e4, 322 0xa23fe467b9de0d83, 0xd11ff233dce8d5a7, 0xe88ff919ee73c38a, 0x7447fc8cf73f171f, 323 0xba23fe467b9dcb2b, 0xdd11ff233dcb0cb4, 0xee88ff919ee26c5d, 0x77447fc8cf775dd3, 324 0x3ba23fe467b9b5a1, 0x9dd11ff233d9117a, 0xcee88ff919efa640, 0xe77447fc8cf3e297, 325 0x73ba23fe467fabd2, 0xb9dd11ff233fb16c, 0xdcee88ff919adde7, 0xee77447fc8ceb196, 326 0xf73ba23fe4621cd0, 0x7b9dd11ff2379ac3, 0x3dcee88ff91df46c, 0x9ee77447fc88e702, 327 0xcf73ba23fe4131b6, 0x67b9dd11ff240f9a, 0x33dcee88ff90f9e0, 0x19ee77447fcff4e3, 328 0x8cf73ba23fe64091, 0x467b9dd11ff115c7, 0x233dcee88ffdb735, 0x919ee77447fe2309, 329 0xc8cf73ba23fdc736} 330 331 // Columns of the parity-check matrix H of the [64,45]-code used for Flow addresses. 332 // H is a (n x p) matrix with coefficients in GF(2), each column is converted into 333 // a big endian integer representation of the GF(2) column vector. 334 // H is used to verify a code word is a valid account address. 335 var parityCheckMatrixColumns = [linearCodeN]uint{ 336 0x00001, 0x00002, 0x00004, 0x00008, 337 0x00010, 0x00020, 0x00040, 0x00080, 338 0x00100, 0x00200, 0x00400, 0x00800, 339 0x01000, 0x02000, 0x04000, 0x08000, 340 0x10000, 0x20000, 0x40000, 0x7328d, 341 0x6689a, 0x6112f, 0x6084b, 0x433fd, 342 0x42aab, 0x41951, 0x233ce, 0x22a81, 343 0x21948, 0x1ef60, 0x1deca, 0x1c639, 344 0x1bdd8, 0x1a535, 0x194ac, 0x18c46, 345 0x1632b, 0x1529b, 0x14a43, 0x13184, 346 0x12942, 0x118c1, 0x0f812, 0x0e027, 347 0x0d00e, 0x0c83c, 0x0b01d, 0x0a831, 348 0x0982b, 0x07034, 0x0682a, 0x05819, 349 0x03807, 0x007d2, 0x00727, 0x0068e, 350 0x0067c, 0x0059d, 0x004eb, 0x003b4, 351 0x0036a, 0x002d9, 0x001c7, 0x0003f, 352 } 353 354 // Rows of the inverse I of the generator matrix I = sub(G)^(-1). 355 // sub(G) is a square sub-matrix of G formed by the first (k) columns. This makes sub(G) 356 // an inversible (k x k) matrix. 357 // I is a (k x k) matrix with coefficients in GF(2), each row is converted into 358 // a big endian integer representation of the GF(2) raw vector. 359 // I is used to retrieve indices from account addresses. 360 var inverseMatrixRows = [linearCodeK]uint64{ 361 0x14b4ae9336c9, 0x1a5a57499b64, 0x0d2d2ba4cdb2, 0x069695d266d9, 362 0x134b4ae9336c, 0x09a5a57499b6, 0x04d2d2ba4cdb, 0x1269695d266d, 363 0x1934b4ae9336, 0x0c9a5a57499b, 0x164d2d2ba4cd, 0x1b269695d266, 364 0x0d934b4ae933, 0x16c9a5a57499, 0x1b64d2d2ba4c, 0x0db269695d26, 365 0x06d934b4ae93, 0x136c9a5a5749, 0x19b64d2d2ba4, 0x0cdb269695d2, 366 0x066d934b4ae9, 0x1336c9a5a574, 0x099b64d2d2ba, 0x04cdb269695d, 367 0x1266d934b4ae, 0x09336c9a5a57, 0x1499b64d2d2b, 0x1a4cdb269695, 368 0x1d266d934b4a, 0x0e9336c9a5a5, 0x17499b64d2d2, 0x0ba4cdb26969, 369 0x15d266d934b4, 0x0ae9336c9a5a, 0x057499b64d2d, 0x12ba4cdb2696, 370 0x095d266d934b, 0x14ae9336c9a5, 0x1a57499b64d2, 0x0d2ba4cdb269, 371 0x1695d266d934, 0x0b4ae9336c9a, 0x05a57499b64d, 0x12d2ba4cdb26, 372 0x09695d266d93, 373 }