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