diff --git a/contracts/LinearCodeAddressGenerator.cdc b/contracts/LinearCodeAddressGenerator.cdc new file mode 100644 index 00000000..5b88b4fc --- /dev/null +++ b/contracts/LinearCodeAddressGenerator.cdc @@ -0,0 +1,126 @@ + +/// LinearCodeAddressGenerator allows generating and validating Flow account addresses. +access(all) +contract LinearCodeAddressGenerator { + + access(all) + enum Chain: UInt8 { + access(all) + case Mainnet + + access(all) + case Testnet + + access(all) + case Transient + } + + /// Rows of the generator matrix G of the [64,45]-code used for Flow addresses. + /// G is a (k x n) matrix with coefficients in GF(2), each row is converted into + /// a big endian integer representation of the GF(2) raw vector. + /// G is used to generate the account addresses + access(self) + let generatorMatrixRows: [UInt64; 45] + + /// Columns of the parity-check matrix H of the [64,45]-code used for Flow addresses. + /// H is a (n x p) matrix with coefficients in GF(2), each column is converted into + /// a big endian integer representation of the GF(2) column vector. + /// H is used to verify a code word is a valid account address. + access(self) + let parityCheckMatrixColumns: [UInt64; 64] + + init() { + self.generatorMatrixRows = [ + 0xe467b9dd11fa00df, 0xf233dcee88fe0abe, 0xf919ee77447b7497, 0xfc8cf73ba23a260d, + 0xfe467b9dd11ee2a1, 0xff233dcee888d807, 0xff919ee774476ce6, 0x7fc8cf73ba231d10, + 0x3fe467b9dd11b183, 0x1ff233dcee8f96d6, 0x8ff919ee774757ba, 0x47fc8cf73ba2b331, + 0x23fe467b9dd27f6c, 0x11ff233dceee8e82, 0x88ff919ee775dd8f, 0x447fc8cf73b905e4, + 0xa23fe467b9de0d83, 0xd11ff233dce8d5a7, 0xe88ff919ee73c38a, 0x7447fc8cf73f171f, + 0xba23fe467b9dcb2b, 0xdd11ff233dcb0cb4, 0xee88ff919ee26c5d, 0x77447fc8cf775dd3, + 0x3ba23fe467b9b5a1, 0x9dd11ff233d9117a, 0xcee88ff919efa640, 0xe77447fc8cf3e297, + 0x73ba23fe467fabd2, 0xb9dd11ff233fb16c, 0xdcee88ff919adde7, 0xee77447fc8ceb196, + 0xf73ba23fe4621cd0, 0x7b9dd11ff2379ac3, 0x3dcee88ff91df46c, 0x9ee77447fc88e702, + 0xcf73ba23fe4131b6, 0x67b9dd11ff240f9a, 0x33dcee88ff90f9e0, 0x19ee77447fcff4e3, + 0x8cf73ba23fe64091, 0x467b9dd11ff115c7, 0x233dcee88ffdb735, 0x919ee77447fe2309, + 0xc8cf73ba23fdc736 + ] + + self.parityCheckMatrixColumns = [ + 0x00001, 0x00002, 0x00004, 0x00008, 0x00010, 0x00020, 0x00040, 0x00080, + 0x00100, 0x00200, 0x00400, 0x00800, 0x01000, 0x02000, 0x04000, 0x08000, + 0x10000, 0x20000, 0x40000, 0x7328d, 0x6689a, 0x6112f, 0x6084b, 0x433fd, + 0x42aab, 0x41951, 0x233ce, 0x22a81, 0x21948, 0x1ef60, 0x1deca, 0x1c639, + 0x1bdd8, 0x1a535, 0x194ac, 0x18c46, 0x1632b, 0x1529b, 0x14a43, 0x13184, + 0x12942, 0x118c1, 0x0f812, 0x0e027, 0x0d00e, 0x0c83c, 0x0b01d, 0x0a831, + 0x0982b, 0x07034, 0x0682a, 0x05819, 0x03807, 0x007d2, 0x00727, 0x0068e, + 0x0067c, 0x0059d, 0x004eb, 0x003b4, 0x0036a, 0x002d9, 0x001c7, 0x0003f + ] + } + + access(self) + fun invalidCodeWord(forChain chain: Chain): UInt64 { + switch chain { + case Chain.Mainnet: + return 0 + case Chain.Testnet: + return 0x6834ba37b3980209 + case Chain.Transient: + return 0x1cb159857af02018 + default: + panic("unsupported chain") + } + } + + access(self) + fun encodeWord(_ word: UInt64): UInt64 { + + // Multiply the index GF(2) vector by the code generator matrix + + var codeWord: UInt64 = 0 + var word = word + + for generatorMatrixRow in self.generatorMatrixRows { + if word & 1 == 1 { + codeWord = codeWord ^ generatorMatrixRow + } + word = word >> 1 + } + + return codeWord + } + + /// Returns the address at the given index, for the given chain. + access(all) + fun address(at index: UInt64, chain: Chain): Address? { + // The index must be in the range [1 .. 2^45 - 1] + if index < 1 || index > (2 << 44) - 1 { + return nil + } + return Address(self.encodeWord(index) ^ self.invalidCodeWord(forChain: chain)) + } + + /// Returns true if the given address is valid, for the given chain code word. + access(all) + fun isValidAddress(_ address: Address, chain: Chain): Bool { + + let address = UInt64.fromBigEndianBytes(address.toBytes())! + var codeWord = self.invalidCodeWord(forChain: chain) ^ address + + if codeWord == 0 { + return false + } + + // Multiply the code word GF(2)-vector by the parity-check matrix + + var parity: UInt64 = 0 + + for parityCheckMatrixColumn in self.parityCheckMatrixColumns { + if codeWord & 1 == 1 { + parity = parity ^ parityCheckMatrixColumn + } + codeWord = codeWord >> 1 + } + + return parity == 0 && codeWord == 0 + } +} diff --git a/flow.json b/flow.json index eee5f98e..27e2eaf9 100644 --- a/flow.json +++ b/flow.json @@ -107,6 +107,12 @@ "testnet": "9a0766d93b6608b7" } }, + "LinearCodeAddressGenerator": { + "source": "./contracts/LinearCodeAddressGenerator.cdc", + "aliases": { + "testing": "0x0000000000000007" + } + }, "LockedTokens": { "source": "./contracts/LockedTokens.cdc", "aliases": { diff --git a/lib/go/contracts/internal/assets/assets.go b/lib/go/contracts/internal/assets/assets.go index 3a1b30a7..a903bec9 100644 --- a/lib/go/contracts/internal/assets/assets.go +++ b/lib/go/contracts/internal/assets/assets.go @@ -7,6 +7,7 @@ // FlowStakingCollection.cdc (64.719kB) // FlowStorageFees.cdc (9.13kB) // FlowToken.cdc (13.18kB) +// LinearCodeAddressGenerator.cdc (4.793kB) // LockedTokens.cdc (33.789kB) // NodeVersionBeacon.cdc (22.87kB) // RandomBeaconHistory.cdc (15.864kB) @@ -223,6 +224,26 @@ func flowtokenCdc() (*asset, error) { return a, nil } +var _linearcodeaddressgeneratorCdc = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x97\xdf\x6f\xdc\xb8\x11\xc7\xdf\xf7\xaf\x98\xde\xc3\x61\x17\x70\xd6\xa4\x48\x49\x54\x9a\x4d\xd1\x04\xbd\xa4\x40\xf3\x52\x5c\xdb\x87\x20\x3e\x50\xe4\xd0\x16\x6e\x2d\x19\x92\xd6\x76\x90\xcb\xff\x5e\x70\x28\x2d\xb5\xd2\x6e\x12\x14\xf5\x8b\x47\xfc\xf1\xe1\xf0\x3b\xe4\xec\x70\x75\x7d\x7d\x0d\xff\xa8\x6a\xd4\xed\xdb\xc6\xe2\x5f\xad\x6d\xb1\xeb\xde\x61\x8d\xad\xee\x9b\x16\xf4\x7e\xdf\x3c\x75\x70\x1b\x1a\xaa\xfa\x16\x74\x6d\xe1\x51\xef\x2b\x1b\x3e\x7f\xd9\x37\x4f\xa0\x8d\x69\x0e\x75\x0f\x3a\x4c\xc7\x6e\xbb\xd2\xc6\x60\xd7\xad\xf5\x7e\xbf\x59\x99\xa6\xee\x5b\x6d\xfa\x6f\x2d\xf4\x65\xb5\x02\x00\x98\x4e\xf3\xdf\x58\x1f\xee\xe1\xed\x9d\xae\xea\x97\xf0\xaf\xbf\xd7\xbd\x82\x2f\xd4\x7e\x6e\xac\xff\x33\xba\x43\xf8\xa0\xab\xba\xc6\x7e\xf5\xfd\x91\xbf\x62\xd7\xff\xe0\xc8\x56\xd7\x5d\x85\x75\x4f\xcd\x5f\xc3\x0c\x2f\xde\x3f\xbd\x3e\x8d\x83\xfe\x0e\x47\x99\x9a\x16\xee\x75\xdf\x56\xcf\xf0\x6e\xec\xf9\x98\xc9\x2b\x99\x7e\x7a\x61\x1a\x8b\x70\xe8\xd0\x82\x6b\xda\x41\xbc\x28\xda\xc8\x7c\x07\x55\x07\x1a\xd6\xbf\xc3\x33\xd4\x9b\x11\xf6\x54\xf5\x77\x60\x1a\x74\xae\x32\xde\x93\x0e\xaa\x1a\xde\xfd\xb2\x4e\x36\x57\x80\xda\xdc\x41\xdb\x3c\xf9\x89\xa6\xa9\x1f\xb1\xed\xd1\x42\x55\xf7\xcd\x11\xaa\xa1\xac\x6e\x01\x6b\x5b\xe9\xda\xf7\xe0\x2d\xb6\xd0\xe2\x43\x8b\x1d\xd6\xbd\xee\xab\xa6\x1e\xbd\x25\x28\xb4\xfa\x09\x1e\xd1\xf4\x4d\x3b\xf3\x8c\xfc\xef\x9b\x71\xbb\x48\x73\x16\x67\x60\x1a\xcf\x0e\xf7\x2e\x08\xba\xc7\x3e\xca\xf4\x81\x36\xe6\x15\x7c\x09\x1f\x7d\x78\x33\xf9\x67\x90\xe9\xa7\xa8\xee\xdb\x66\x7f\xb8\xaf\x8f\x02\x3f\xe8\xb6\xea\x3f\xbf\x30\x77\x68\x7e\x1f\x65\x79\xff\xbf\x69\xfc\x7e\xd0\xb8\x86\x67\x78\xf8\x71\x8d\x0d\x39\xf4\xff\x94\x79\x20\xce\x95\x7e\x3f\x55\xfa\x11\xdb\xca\x7d\x06\x0d\xb4\xb7\xa7\xa6\xb5\xc1\x7b\xba\x88\x73\xe9\xb7\x97\x95\x0f\xfa\xbd\xf5\xf2\x05\xed\x07\x7d\x27\xf2\x67\x72\x90\xbf\xaa\xab\x7e\xbd\x99\xdc\x37\x8f\xda\x9e\x89\x1d\xec\xe0\xe3\x71\x90\xff\x63\xcf\x28\xb3\xbc\x2c\xac\xe5\xdc\x69\xc6\xac\xbb\x02\xf6\xec\x12\x21\xac\x41\x54\xca\x21\xd3\x25\x52\x5b\xc1\x0b\xc4\x3c\x97\x32\x2f\x73\x59\xe4\xd4\x66\x94\x71\xb9\x28\x75\x22\x74\x92\x31\x7b\x35\x63\xbb\x08\x47\x4c\x34\xa7\x39\x11\xae\xac\x62\x81\x33\x81\x67\x06\x33\xdf\x96\x4f\xe0\xdc\x72\x36\x67\x8b\x09\xbc\xe4\x4a\xf8\x39\x3c\xc2\x5d\x91\x59\xe2\xa8\x08\xcf\xd3\xbc\xd4\xbe\x4d\x4e\xe0\xa5\x10\x7c\xce\x4e\x22\x3c\xc9\x5d\x66\x88\x1d\xe1\xa8\x50\x25\xc4\x8e\xf0\xd4\x5a\x45\xda\xc9\x08\x2f\x58\x8a\x72\xce\xd6\x11\x8e\xcc\x06\xbf\x6d\x84\x2b\x9b\x6a\xd2\x04\x23\x5c\x18\xa1\xc8\xef\x3c\xc2\x1d\xcf\xb9\x9b\xb3\xcb\x09\xdc\x94\x49\x49\xec\x08\x2f\x99\x29\x25\xb1\x23\x3c\xc9\x4c\x6a\x89\x1d\xe1\x7e\x33\x62\xa1\xf7\x04\x5e\xa6\x21\x96\x45\x84\x17\x9c\xe7\xe4\xa3\x89\x70\xa7\x33\xc9\x68\xbd\x08\x17\x98\x14\xf9\x9c\x9d\x47\xb8\xd3\xa5\x25\x6d\xcb\x08\x77\x25\x0f\x31\xb0\x11\xae\xad\xc5\xa0\x53\x84\x63\xc9\x8b\x6c\x71\x06\x23\x3c\xe1\xc6\x92\x3f\x79\x84\xe7\x85\x36\x14\x03\x11\xe1\xd6\xc9\xb0\x5e\x11\xe1\x0a\x73\x96\xcc\xd9\x26\xc2\xb9\xe0\x25\x9d\xb7\x2c\xc2\x25\x73\x05\x69\x22\x22\x9c\xb9\x02\xc9\x07\x1e\xe1\xce\x49\x5c\xe8\xad\x22\x3c\x93\xac\x20\xbd\xe3\x55\x75\x9c\xa7\x86\xf6\x1f\xaf\xaa\xb3\x65\x2e\x52\xf2\x3b\xc2\x31\x11\xac\x58\xf8\x1d\xe1\xd6\xe4\x22\x3b\x76\x7f\x5a\x9d\xa6\x90\x4b\x49\xe8\x4c\x1e\x61\x8c\x31\x72\xd2\x1b\xc9\x68\xc8\xd1\x50\x83\xc1\xd9\x60\x24\xa3\x21\x47\x43\x2d\xee\xb8\x1f\x3e\xf4\x26\xa3\x21\x47\x43\x0d\x06\x67\x83\x91\x8c\x86\x1c\x0d\xe5\x8d\x19\xd3\x0f\xa7\xde\x64\x34\xe4\x68\xe4\x22\x51\x74\x17\xb2\x4c\x85\xc0\x65\x9c\x27\x74\xab\x33\xa6\x24\x5d\x27\x29\x84\x5b\xe4\x39\x99\x68\x1d\x7a\x79\x91\xf2\x21\x2a\x86\xd2\x66\x92\x68\x15\x5a\x78\x21\x49\x04\x8e\x2e\x0b\x27\xc0\xa2\xa1\x55\xb8\xc9\xc4\x22\x46\xbc\xb4\x36\x8c\xd7\x69\x88\x2a\x2f\xa4\x0e\xa9\x48\x19\x49\x67\x8d\x67\x22\x5c\x72\x9e\x26\x45\x30\xa4\x96\x21\x15\x0a\xae\x16\xb9\x87\x27\x85\x4c\x42\x32\x53\x26\x04\xcb\x29\x1e\x82\x85\x2c\xa1\xf3\xc4\x2c\x63\xe4\x39\x33\x4a\xd0\x72\xac\x64\x9c\x64\x61\x5a\x2d\x73\x25\x2b\x54\xf0\x81\xe5\x4c\x84\x70\x67\x2a\xa1\x7d\xb1\x54\xf1\x82\x0c\x31\x24\x7a\xc6\x72\x3b\x9c\x8d\x7c\x58\x8e\x65\x0a\x97\x71\xcf\xf2\xb0\x34\x4b\x0b\x3b\xc4\x1d\xc3\x2a\x4c\x94\xc3\xa1\x12\x99\x1e\xce\x86\x0d\xab\x30\x6e\x06\x26\x13\x6e\x72\xa6\x21\x96\x81\x8b\x9f\x5a\x77\xf0\x3f\xfd\xf4\xe3\xec\x8b\xdd\xff\x34\xad\x5d\xbb\xa6\xa5\x3a\x16\x4c\xa8\x66\xe9\x63\x13\xaa\xda\x4c\x4e\x7f\x66\x9f\xaa\xde\x17\x1a\x34\xf8\xcb\x69\x15\x4a\x93\xb6\x43\x7d\xfb\xf2\x64\x83\x2d\xf6\x87\xb6\x06\x76\x6e\xc2\x50\xe6\x9e\x9f\xf0\x9c\x29\x21\x4b\x2d\xf2\x52\x14\x8a\x25\xac\x38\x4b\x18\xcb\xdf\x0b\x0c\x6e\x4a\x9e\x16\x2a\xcd\xb5\x63\x09\xe3\xea\x38\xca\xa2\xd3\x87\xfd\x6c\xda\x83\xae\x2b\xb3\xfe\xe9\x50\x77\x87\x87\x87\x86\x6a\x28\xda\xee\x4f\xb1\xe8\xfe\xfa\x5d\x81\xb1\x36\xa3\xb6\xbf\x51\x49\x34\x6a\x39\x15\xf5\xc8\xbb\xbe\x86\x0f\x87\x7d\x5f\x3d\xec\x3f\x53\xed\x55\xd5\x16\x9f\x87\x0a\x2c\x94\x5e\x50\x86\x1e\x2a\xb1\xe6\x95\x7c\x04\x3d\xea\x16\xc6\x85\x8f\x0b\xed\x26\xba\xfb\x01\x54\xa1\xed\xe8\x5f\x9c\xe9\xab\xd1\x65\xf9\xe4\x0b\xcc\x8b\x95\xd5\x97\x13\xd9\x2a\x17\xc0\x3f\x03\x87\xdd\x0e\xf8\xac\x9b\x42\x36\x78\x06\xbb\x68\xde\x9c\x59\xf5\x64\xe2\xd7\x93\xaf\x89\xef\xf0\xfa\x35\xf0\x49\x48\x56\xb3\xb8\x8f\x4b\x2c\xde\x44\xd4\xdd\x85\x77\x41\x28\x4a\x41\xf7\xe1\x89\x54\x3d\x62\x1d\xd4\xbf\x22\x45\x62\x23\x1d\x81\xed\xd9\x67\xa0\x8f\xf7\x00\x5a\xeb\x3e\x4c\x1f\xc5\xbf\x9a\xdf\xa8\xe1\x6d\xf9\x97\x89\x3c\xd7\xd7\xf0\xeb\x31\xe8\xf7\x87\xae\x87\xd2\x7f\xd1\xe2\xad\xae\x6f\x11\x3e\x72\xd8\x6e\x21\xb9\x91\x29\xbc\x00\xfe\x69\x35\xd1\x3c\xcc\x7a\x05\x1c\xfe\xf8\x63\xf8\x78\x0d\xeb\x04\x5e\xbd\x02\x29\x37\x7e\xf8\x2c\x10\x83\x3a\x75\xb5\x5f\x2d\x25\x1e\x3a\x07\x27\xe9\x4c\x6f\x27\x47\x99\xf8\x1b\xb8\x09\x67\xe2\x52\x12\x79\x19\xf6\xbc\xd9\x5c\x54\xbe\x3d\xa0\xf7\x3d\xaa\x3b\xc6\xa1\xea\xc2\xab\xe1\xac\xfa\xf1\x7d\x71\x39\x0e\x55\xf7\x6f\x3f\x7f\xdc\xc0\x6f\x23\xf9\x28\xfc\x22\x20\x6f\x9a\x66\x3f\xbd\x8b\xfe\x25\x32\xba\xb3\x1b\xa2\xb8\x75\x6d\x73\xff\xa6\xba\xfd\x1b\x3d\x9c\xde\x7c\xee\xb1\x5b\x8f\xef\x99\xbe\x09\xdf\x9b\xcd\x9f\xce\x5e\x43\xd8\xfd\x98\x5a\x70\x33\x2e\xbb\x9a\xc6\x37\x62\x76\xc0\xce\x87\xd2\xe9\x7d\x87\xe7\x2e\xc2\x3c\xad\xc4\xf7\x19\xa5\x96\x17\xa7\xa9\xe5\xcc\xf3\xf5\x34\xb1\x84\x01\x27\x69\xe5\x24\x7d\x5c\x28\x9d\x8e\x39\xe4\x62\x69\xb5\x48\x24\xc7\x4d\x7f\x23\x99\x04\x1a\xec\x46\xe3\xe6\xd2\xfa\xdf\xc8\x26\xe7\x12\xd2\x77\xb2\xca\xb8\xac\x8f\xc6\xcf\x3f\x9f\x86\x67\x38\xef\x5f\x57\xff\x0d\x00\x00\xff\xff\xb2\x90\x98\x61\xb9\x12\x00\x00" + +func linearcodeaddressgeneratorCdcBytes() ([]byte, error) { + return bindataRead( + _linearcodeaddressgeneratorCdc, + "LinearCodeAddressGenerator.cdc", + ) +} + +func linearcodeaddressgeneratorCdc() (*asset, error) { + bytes, err := linearcodeaddressgeneratorCdcBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "LinearCodeAddressGenerator.cdc", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb4, 0x72, 0xa5, 0x27, 0xf3, 0xdb, 0xd2, 0x1f, 0x41, 0xd7, 0x3b, 0xa9, 0x7a, 0x64, 0xd2, 0xe0, 0x99, 0xa1, 0xc1, 0x1, 0x11, 0xd2, 0xf8, 0xaa, 0x76, 0xef, 0x88, 0x74, 0xc8, 0xfe, 0x91, 0x3d}} + return a, nil +} + var _lockedtokensCdc = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x5b\x73\x1b\x37\xb2\xf0\xbb\x7e\x05\xac\x07\x87\xda\x95\xa9\xfd\xf6\x3b\x75\x1e\x54\x52\x1c\xc5\x8a\xcf\xaa\x72\x71\x4a\xb6\x4f\x1e\xb6\x52\x5b\xe0\x4c\x53\x44\x3c\x1c\x4c\x00\x90\x8c\xd6\xe5\xff\x7e\x0a\xd7\xc1\x75\x66\x48\x39\x8e\x73\x8e\xf4\x62\x73\x06\x68\x34\xba\x1b\x7d\x43\x03\x73\xf6\x97\xa3\x23\x84\x10\xfa\x8e\x56\xef\xa0\x7e\x43\xdf\x41\xcb\x11\x59\x77\x0d\xac\xa1\x15\x1c\x89\x15\xa0\xe5\xa6\xad\x04\xa1\x2d\x6e\x88\xb8\x47\x0c\x7e\xdd\x10\x06\x35\x12\x14\xad\x71\x8b\xef\x00\xbd\xfc\xee\xd5\x4f\x0a\xca\x62\x73\x0f\x8c\xa3\x46\x01\x43\x42\x43\x5b\x32\xba\x56\x70\xd4\x6f\xc4\x71\x03\x73\x3d\xe8\x37\xb8\x5a\x99\xa7\x2b\xda\xd4\xc0\xd0\x1d\xc8\x31\x77\x14\xe1\xaa\xa2\x9b\x56\xf0\x39\x7a\xd5\x82\xfd\x85\x88\x42\x88\xb0\x60\x04\x05\xca\xb4\x98\xa3\x1b\x81\x76\xa4\x69\xd0\x02\xd0\x2f\x94\xb4\xa2\xb9\x47\x15\x6d\x05\xa3\x4d\x03\x35\x5a\xdc\x2b\x4c\x36\x1c\x18\xc2\x6d\xed\xa1\x85\xeb\x35\x69\x09\x17\x0c\x0b\xca\xe6\x0a\xe6\x9b\xfc\x4b\xb4\xde\x70\x81\x2a\xfa\x8c\x93\xbb\x56\x43\x60\xb8\xe5\x4b\x60\x88\x2e\x11\x6e\xef\xc3\xf9\x67\x61\xa1\x0a\xb7\x2d\x15\x88\xb4\x02\x18\xae\x24\xce\x62\xa5\x60\x99\x89\xa8\x4e\xf2\x21\xdd\x08\x84\xbb\x8e\xd1\x2d\x6e\x62\x52\x6a\xa2\x9d\xaa\xb6\xf0\x5b\x05\x9d\x90\x4c\xa9\xa1\xa3\x9c\x08\x84\xeb\x9a\x68\xb6\x59\x84\x1c\x9f\x28\x93\x0d\x37\xad\x7c\x8e\xe0\x37\xc2\x05\x69\xef\xd4\x6b\x84\x05\x02\xc9\x96\x35\x69\x80\x0b\xda\x02\x22\xad\x37\xe4\x16\x74\xdb\x0e\x18\xa1\xb5\xe1\xa3\x9c\x1c\x87\x8a\xb6\x75\xc4\x29\x33\x04\xd4\x86\xe2\x96\x49\x6f\x56\x84\x7b\x4d\x15\x10\xd2\xa2\xe5\xa6\x69\x50\x47\x39\x07\x4e\x68\xab\x18\x64\x78\x27\x29\x1b\x33\xee\x5e\x12\x11\xd5\x14\xed\x56\x58\xc0\x16\x98\x02\xa3\x5e\xec\x70\x6b\x48\x4a\xe2\xd1\x94\x70\x70\x41\x19\x20\x8c\x2a\xdc\xe1\x05\x51\x62\x2d\x56\x58\x20\xdc\x34\x74\xc7\x2d\x9c\xb5\x24\x92\x84\x52\x33\xbc\xb3\xd2\xbc\x5b\x41\xab\x07\x59\x40\x45\xd7\xde\x14\x25\x5a\xb8\xe1\x14\x09\xaa\x20\x74\xc0\x96\x94\xad\x11\x17\xf8\x9d\x24\x19\xed\x80\x61\xc9\x10\xee\xb8\x1d\x49\x32\x37\xf4\xfc\x49\x8e\x81\x03\x9a\x49\x82\x56\x0c\xb0\x80\xfa\x14\x2d\xa8\x58\xb9\x15\x82\x30\x93\x3c\x22\x82\xe0\x86\xfc\x1b\x6a\x05\xdc\x4e\x81\x30\xc4\x80\x77\x50\x09\xb2\x05\x44\x17\xbf\x40\x25\xf8\xb9\xbf\xda\xbf\x57\x4b\x98\xa1\xa5\x94\x09\xc9\xc7\x15\x96\x8b\xdb\x40\xd7\xb2\x25\x67\xa6\x1a\xff\x43\xaf\x52\xdb\xb6\x9f\x7a\xcf\x58\xc3\xa3\x0a\x37\x0d\x77\x9a\x43\x93\x94\xb6\x01\x94\x0c\x71\x9d\x7c\x87\x58\x68\x8e\xe7\xa9\x8a\xab\x90\xa4\x21\x41\x8f\x8e\xd0\x5f\xce\x8e\x8e\xc8\xba\xa3\x4c\xa0\x97\x0d\xdd\x29\x0c\xf4\x40\xc7\xee\xf7\xb1\x6b\xb1\x69\xef\xc8\xa2\x81\xa0\x95\xff\xec\xd8\x87\x75\x73\xfd\x06\x2f\x1a\x78\x6d\x50\xe9\x81\x86\x2f\x82\x3e\xaf\x05\x65\xf8\x0e\x5e\x02\x70\xaf\x83\xf7\xd4\xb5\x36\xbd\x7f\x64\xf4\xb7\x7b\xd3\xd4\x7f\x74\x7c\x74\x84\xab\x0a\x38\x9f\xe1\xa6\x39\xd1\x0b\x45\x6a\x92\x40\x93\xbf\x3f\xb2\xda\xd1\x35\x84\x2d\xb4\x02\xbd\x56\x04\xbe\xd2\xf4\xbd\x85\x3b\xc2\x05\x30\xa8\x67\xb8\xae\x19\x70\x7e\x8e\xae\xf4\x7f\x4e\x0a\xfd\xdf\x1a\xd6\x4f\x81\x30\x08\xe2\x3b\xb2\x26\xe2\xa6\x95\xb2\xcd\x33\xbd\x4f\x11\x31\xef\xae\xd6\x72\xa0\x73\xf4\xf6\x25\xf9\xed\x3f\xff\xe3\x14\xb5\xb0\x53\x7d\xed\x93\xe2\x38\xdf\xe5\x11\xbd\xe2\x3f\xd0\x1a\x32\x03\xb6\xb4\x86\x9b\xeb\x73\xf4\x5a\x30\xd2\xde\x95\x08\x50\x84\x7a\x0d\x0d\xdc\x49\x3b\x31\x01\xf4\x20\x6c\xcd\xc2\x6b\xad\xcd\xb3\xa4\xc1\x01\x49\x0c\xb8\xb3\xb3\x33\xf4\x23\x96\x8b\x81\x1a\x3d\x17\xaf\x0a\x63\xb6\x95\x6a\xa0\x1b\x56\x81\xeb\x67\x54\x7d\xb8\xfa\x12\x24\x1b\x10\x19\x0d\x62\x44\x58\x0e\x2d\x27\xe8\x7e\x0c\x61\xd5\x31\xb2\xc5\x02\x7c\x3d\x6c\x75\x4b\x6f\xda\x65\x57\x83\xf1\x44\x54\x7e\xd4\x60\x35\x2a\xde\x8f\x29\xa8\x04\x84\xd2\xb6\xba\x21\xed\xbb\x87\x91\xe8\x4a\xc2\x39\x04\x2b\xe3\x2c\x48\xe7\x45\xe9\xb9\x18\x0d\xfd\x7e\x1f\x2c\x5e\x38\x58\x87\x30\x2c\x70\xd6\x4a\xe2\x13\x9b\x85\x2c\x5e\x9e\x25\x98\x80\xc8\x66\xd1\x90\x0a\x75\x09\x3e\x03\x06\x5c\xf6\x63\x80\x6b\xa9\x99\x49\x2b\x6d\x86\x32\xbe\x08\x2f\x94\x4b\x85\x26\xe0\x18\xac\xf1\x9b\x76\x49\x35\x1e\x86\x83\xee\xff\x31\xc1\x14\x22\x8e\x2b\xda\x6c\x53\x86\x76\x74\xd3\xd4\x1a\x77\xd7\x41\xce\xc1\x92\x51\x77\x54\xae\xc5\x86\x4b\x52\x1b\x83\x1f\x61\xca\xc7\x51\x7d\xa1\x47\x9c\xca\xe0\x41\x7c\x3b\x39\x4d\xbe\xf2\x31\x26\xac\xb8\x60\x8d\x40\x1a\x5b\x2d\xdb\x5b\x6f\xd4\xf3\x6d\xf5\x08\x92\x17\x3d\x98\xc9\x93\x1a\x63\x81\xf4\x40\x7a\x69\xf7\x11\xd5\xb2\x51\x72\xf9\x3d\x87\xd8\x38\x23\xc6\x13\xee\x75\x50\xec\x11\xc7\xbe\x70\x3c\x05\xc7\x58\xe5\xe5\x2f\x71\x15\x60\xf6\x5e\xb5\xf7\xfa\x68\x7b\xa8\xb5\xfe\x89\x74\x9d\x9c\xe9\xf3\x2c\xe5\xac\x86\x46\xe0\x5e\xe5\xcb\xfe\x1f\xfa\xd9\x7f\xd3\x0a\x22\x74\xec\x56\x60\x4c\x34\x49\xe9\x57\x04\xd2\xd8\x07\x69\xca\xeb\xda\x62\x46\xe8\x86\xa3\x3b\x86\x73\xa2\x07\xde\x78\x3e\xfe\xfb\x61\xa4\xa5\x9d\x41\x45\xb7\xc0\x50\xa3\x3c\x01\xeb\xc0\x39\x39\x22\x0c\x2a\x19\xcd\x29\x4f\xc8\x39\xbf\xbb\x15\x45\x2b\xbc\x85\xb0\x97\x04\xa7\xdd\x6d\x50\x36\xb7\x07\xf3\x9a\xb4\x6a\xa5\x81\xf4\xff\x99\x7c\xdb\xc7\x3f\x4e\x56\x08\x38\x7f\x92\x70\x7f\x8e\xa7\xbd\xaa\x53\x1e\x39\x6d\x1b\xb5\x58\x6b\x1d\x16\xe0\x8d\x58\x51\x46\xfe\xad\xfc\x52\x1d\x15\x6a\xf7\xd4\x2a\x27\xa9\x8f\xee\x1d\x8c\x15\xe6\x86\x98\x12\xdf\x38\xf8\x2b\x91\xf9\x56\x93\xe9\x3b\x39\x5f\x5f\xec\x65\xc4\x95\xb5\xee\x12\x51\xa5\x75\xea\xbc\xf1\xf2\x02\x79\x3d\x66\x2f\x0f\x34\xf5\x1d\xb6\x78\xd3\x58\x87\x5c\x03\xd3\x3e\xe9\x59\xad\xfd\x1e\x39\x77\x3b\x32\x1f\x58\x13\xa9\xd5\x3e\x0f\xbd\xef\xf9\x2d\x54\x40\xb6\xc0\x4e\xa3\xe7\x3f\x32\xba\x25\x32\xee\x0d\x57\x93\x5b\x4e\x8e\x1c\x32\xea\x43\x0c\x96\xc0\x40\x31\x5d\xe3\x5b\xc3\x52\x4d\x41\x45\xbb\x7a\x36\x43\xd4\x99\xfb\x70\x83\x31\xae\x9a\x20\xb0\x76\x6a\x83\x41\x00\x90\x70\x3d\xca\x29\xda\xad\x48\xb5\x52\x41\xeb\xc2\x92\xda\x34\xda\x51\xb4\xc3\xf7\xfc\x3c\x80\x8f\xd0\xff\x3b\x41\xd7\x46\xec\xa5\x1f\x1c\xc9\x94\xc9\x40\xe8\xac\x86\x0a\x09\x13\x0b\xad\xd9\x94\xe8\xba\x68\x98\xbf\x9f\xa0\x9b\xd6\xad\xaf\x2d\xc1\x0a\x50\xca\xa0\x0c\x0e\x3d\x02\xf1\xd8\xb1\x76\x33\xe4\x3c\x91\x1a\x45\x13\xe4\x1c\xbd\x70\xca\xf9\x42\x2e\x9d\x59\xc8\xe7\x9f\x4c\x70\x78\x82\x9e\xba\x40\x6d\xfe\xdf\xb2\xe7\x97\x31\xb3\xc1\xb8\xc2\x2a\x4d\x60\x34\x80\x31\xa6\x36\x1c\x6d\x5d\xb0\x19\x70\x14\xdd\xa8\x85\x5c\x83\x09\x40\x5c\x7c\xaf\xfb\xd9\x3e\x3c\x99\x8e\x14\x66\x39\x95\x4d\xaf\x9b\xad\x56\x0e\xb1\x7b\xd5\x99\x24\x8c\x0c\x37\x64\x00\xe7\x2d\xcd\x39\xfa\x89\x34\x8d\x56\x23\x0b\x40\x4b\xa2\x92\x54\xa4\xcf\x75\x04\x90\x24\xb1\x39\xda\x74\x52\x92\xa5\x04\x29\xd5\x66\xf4\x1c\x4d\x08\x6e\x03\x42\x8d\x66\xeb\x06\x3f\x47\x5f\xa5\x21\xea\xbc\x47\xee\xf9\x00\xfa\x2e\xb6\xf9\x58\x33\xa8\x2d\xc0\x71\xec\xdd\xd8\xe5\x09\xb8\x26\xde\x1c\x48\x4b\xc4\xec\xa1\xf2\x76\xe2\x59\x6b\xf9\xc7\xa1\x59\xce\xb5\xee\xb8\xd4\xc2\x9c\xbe\xee\x29\x8e\x2e\x9e\xa1\x96\x34\xf9\x26\x3d\x49\x4b\xad\x3c\x09\x43\x97\xe8\x6f\xf3\xbf\xb9\x26\x1f\x7c\x56\x15\xb4\xa7\x4d\x90\xe4\x05\x98\xc0\x4e\x79\x1a\x77\x20\x5e\x6f\xba\x8e\x32\x01\xb5\x9a\xf2\x9b\xfb\x0e\xf8\xec\xe4\x1c\xbd\x97\xff\x3b\x47\x5f\x53\xda\x7c\x88\xa8\xc0\x40\x6c\x58\xab\x5b\x5c\x7c\x15\xd3\x4c\x76\x16\x6c\x03\x1f\xf2\xe8\x9e\xa1\x5b\xd5\x5d\x65\xd4\xa4\x3d\x46\x54\xf2\x59\xaf\xd9\x3b\xb2\x95\xab\xf0\xbe\x53\xc6\x4b\x62\xdc\x89\x5e\xcd\xd8\xa9\x85\xda\xd8\xe8\x72\xb5\xee\x2b\xed\xce\x42\x27\x54\x3e\x56\x01\xe2\x2b\xe5\xcf\xfe\xb2\xe1\xc2\x62\x2e\xd1\x93\x40\x8d\x49\x18\x26\x11\xe1\x29\x85\x66\x42\x11\x47\xfe\xf7\x44\xd3\x28\x22\x11\x59\x2a\x47\xd6\xeb\x8b\x2e\x35\x57\x4b\x14\xff\xa7\x04\xf9\x33\x7a\x8f\x02\x38\x1e\xb9\x7d\x58\x41\x9b\x0f\x08\x1a\x0e\xe8\xbd\x6d\xb8\xc4\xf2\x67\x91\xfc\x26\xb1\xc0\xfb\x70\xad\xf7\x9d\x94\x77\x5b\x24\x89\xa4\x86\x71\xeb\x67\xd2\x1b\x3b\x47\x5f\xbd\x0f\x85\x4f\x4d\xe8\x43\x76\xd5\x98\x8e\x36\x7f\xa4\xdd\x45\x03\xe6\xe2\x99\xfc\xf7\x24\x87\xb1\x19\x5f\x82\x08\x10\xc8\xc2\x99\x86\x8e\x64\x8c\x9a\xe4\x2d\x2c\x2d\x57\xd4\xef\xf9\x82\x32\x46\x77\xb3\x93\x27\x47\x49\x87\x05\x6e\xb0\x74\x26\x2e\x95\x1f\x3a\x37\x3f\xc3\x76\x16\xe8\x3c\x24\xd2\xc5\x33\xa4\xa7\x97\x12\x65\xc0\xd1\x37\x23\x64\x89\x92\x2c\x7a\xeb\x1a\xb9\x45\x1f\x2e\x11\xfe\x8e\x5b\xd5\x6c\xec\xa5\x71\x46\xac\x99\x6b\x6d\x06\xd6\x3a\x2d\x63\x4b\xe2\x6a\x8b\x49\x83\xd5\xf8\x56\x7d\xce\xa2\xac\x54\x76\x5d\x4c\xa1\x7d\x46\xf6\x0d\xd6\x17\x97\x3d\x8d\x2d\x43\x9e\x3e\xf5\xde\xc6\x7a\xb3\xb4\x06\x2c\xce\xe9\x22\x70\x99\xe8\x2c\x19\x4a\x86\x43\x12\x65\x57\xa4\x43\x5e\x2c\xf3\x4a\xf5\xe2\x99\x9a\x83\x05\x16\x89\xb9\x05\xad\xff\x9d\xb6\x60\x46\x40\xed\x87\x65\xc7\x20\x7a\x82\x72\xe6\xea\xcb\x4b\x97\xa3\x3c\xbe\x85\x5f\x37\xc0\xa5\xd6\x32\x7c\x82\xdf\x2a\x80\x3a\x26\x3d\x6a\x64\xcf\xe3\x50\xb3\x85\x4b\xa6\xa3\x5c\x4c\x19\xfd\xf2\x12\x2d\x60\x49\x19\xcc\xe2\x57\x27\xe8\x59\x8f\xd8\xdb\xae\xc6\x12\xad\x1c\x1e\xd2\xfc\x90\xb6\xa2\x4c\x3a\xc7\x83\x48\x1d\xa4\x4d\xb4\xc9\xba\x78\xd6\x8b\x73\x22\x3d\x96\xc5\x39\x4d\x5a\x54\x1a\xd9\x4e\x4e\xb2\x42\x91\x4e\x65\x26\x71\x0d\xbe\xd6\x6b\x4c\x5a\x74\x2d\x26\x1f\x67\x35\xc7\x6b\x78\xa2\xde\x1f\xcb\x89\xe4\xac\x4e\xe8\x43\x25\x8f\x9e\x21\x05\xa2\xa0\x63\xfd\x74\xfc\xdc\x8b\x39\xb3\x4a\xf6\x05\xf6\x37\x9a\x75\x8e\x03\xb6\xc0\xee\x91\x20\x6b\xe9\xf2\xda\xac\x11\x03\x95\xb2\x40\x2b\xdc\x75\x90\xfa\x67\x87\x64\x83\x0e\x98\xf9\x5f\xa3\x99\xcb\x3f\x90\x2f\x86\x77\x67\x14\x1c\xba\x6b\x81\x3d\x99\xe3\xd2\x4e\x8d\x82\xec\x6f\xd4\x24\xcb\x70\x32\xc1\xcd\x96\x61\x96\xe2\x76\xf3\x45\x46\xfb\x2d\xec\xc2\xa8\xa8\xdf\x17\x94\xfe\xa9\xdd\x53\x73\xbb\x65\x01\x20\xbd\xdf\xbc\x5e\x4b\xa7\x08\xb7\x76\x4f\xd5\x0b\x2d\x13\x3f\x89\x4b\xff\xbe\x18\xe9\x4a\xa6\x31\x83\x9c\xda\x6b\x52\xdb\x3f\xed\x92\x9e\x07\x7b\x7b\x2a\x74\x91\x8f\x93\x0d\x9d\xbc\x33\x19\x06\x16\xf9\x58\x23\xa3\x1e\x65\x57\x93\xab\x91\x83\xa1\xcb\xcc\x16\xa6\x43\x65\x66\x77\xaa\x7a\xc8\x73\x52\x47\x0a\x45\xcd\x99\x73\x60\x62\x96\x3c\x57\xf2\xd7\x8f\x36\xd7\x34\x53\x90\x6a\xf4\xd7\xcc\xab\x17\x8a\xf0\xa2\xf0\xf6\x6d\x6b\xf7\x7b\xcb\x6f\x0b\x5d\x6f\x61\x87\x59\x2d\x1d\x6f\x15\x3c\x9d\x66\x51\x5d\x03\xe7\xf8\x0e\xce\xd1\xf1\x0b\x5d\x98\x61\xf9\xe6\xcb\xd4\xa6\x15\xa4\x41\xb8\x69\x12\x27\xa1\x63\xb0\x55\x69\x52\xd5\x4e\xe5\x23\x17\x00\xbd\xcd\x6d\x8f\x93\x51\x33\xb4\xac\x81\x0b\x46\xef\x3d\x9a\x7f\x74\x83\x63\x10\xdf\xdf\xe2\x4c\x12\xbc\x8c\x40\xe1\xba\x96\x32\x75\x0b\x15\x65\xf5\x8c\xd4\x5a\xa2\x14\x7b\x48\x7d\x8a\x18\x6d\xc0\x7b\x24\x7f\x4a\x85\x21\x76\x94\xc9\xee\x57\x56\xdf\xb8\x16\xc9\x3b\xbf\xf9\xb7\x70\x9f\x6d\xfa\x2d\xdc\x9f\x5a\xc9\x08\xdb\xf4\x0f\x4f\x51\x24\x87\xd2\x61\xd7\x8f\x22\x52\x64\xd8\x94\xaa\xcf\x89\x9b\xce\x59\x3d\xea\xaf\x3d\x43\xa9\x82\xa6\x4c\x95\x5f\x9f\x4e\xd8\x43\xf1\xe9\x9d\xb4\xa6\x01\xa6\x72\xd2\x52\xb1\x75\x50\x91\xa5\xb6\x61\x37\xd7\xb6\xfa\x26\x9f\x6f\x32\x10\xee\x55\xe6\xd3\xcb\x02\x9b\x4d\x20\x34\xa2\x19\xfb\xfd\xf2\x70\x77\x7c\xa2\x36\xac\xfd\xfc\x49\x31\xab\x52\xd0\x87\xae\x73\x59\x23\x5e\xfb\x4d\x1c\x8a\xae\xe3\x5c\x3f\x39\xf5\x40\x05\xaf\xf7\x56\x9a\x01\x4a\xb1\xda\xcc\xbd\xf4\x15\x67\xee\xbd\xaf\x3a\xcb\xef\x8b\xdd\x3f\x8a\xfa\xec\x99\xf4\xa9\x74\x68\x9a\x58\x44\x1f\x41\x85\x96\x18\x97\x44\xa3\x5f\x66\x65\xe9\x0e\x84\x13\xa7\xef\x49\x4b\xd6\x9b\xb5\x62\xed\xad\x2e\xa9\x5c\x43\x2b\x66\x27\x29\x85\x7b\xea\x7e\xbf\xe1\x42\x93\x46\xef\x64\xe8\xb5\x46\x5b\xb4\xd6\xd0\xf4\x46\x04\xeb\xc1\xd9\x3d\x0d\xe3\xb9\x98\x14\x19\x0d\xf8\x43\x6b\x08\x49\x9b\x51\xfd\x0f\xb2\x1b\x13\x96\x68\x86\x58\xce\x73\x82\x5d\xaa\x22\xec\xaa\xdb\x57\x67\xf7\x62\xb1\x87\xca\xce\x54\xf4\x8c\xeb\xed\xeb\xa1\xa8\xbc\xdf\x0c\xb1\x51\x96\x16\x38\x65\x1c\x4e\xce\x91\xce\x4e\xe7\xdd\xb3\x57\x46\xff\x9a\x34\x75\x39\x8f\x9f\x09\xd2\x5a\x65\x8a\xa5\xac\x3f\x8d\xcd\x37\xe6\x1f\x67\xd4\x5c\xa0\x67\x86\x3d\x80\x20\x3d\xe9\x07\xa8\xe2\x1a\xbd\x92\x0c\x29\x63\xd8\x6f\x0f\x64\x48\xe3\x24\x23\xa6\x4f\x2f\xa7\x03\x24\xda\x1f\x85\x1c\x9d\x7c\x1c\x4a\x06\xff\xcd\x0a\xd0\x92\x36\x0d\xdd\x29\x1b\xbb\xa3\x7d\x91\xa5\x32\xc0\x0d\x16\xe0\x4a\x7f\xb9\x5e\xeb\x5d\x43\x2a\xf9\x38\x28\xe4\x8e\xec\x37\x16\x68\x87\x39\x6a\x28\xf7\x8a\x91\x5f\x30\xe0\x15\xb4\x35\x45\x9b\xee\x8e\xe1\x1a\x62\x54\x4c\x55\x45\x50\xdd\xa1\x60\xd1\x5d\xab\x4b\x2d\x82\x22\x53\x41\x0d\x5f\xa3\x8d\xd9\xc4\x1b\xd1\x9e\x06\xf3\x54\x47\xb8\xff\x2f\x43\x34\xae\x2b\x5a\x22\x94\xf4\xbe\x6f\xbf\x31\x6f\x02\x71\xe5\x04\xbd\xa4\x9b\xb6\xd6\x0a\x33\xae\x37\x30\x1b\x86\x44\x28\x0f\xc8\xec\x3f\xd0\xd0\xe3\x49\x62\x74\x7f\x2b\x3e\xbb\x96\x5f\x52\xfd\xf2\xf7\x5a\xd3\x46\x6e\x94\xac\xfa\x1a\x64\x60\xa5\x0d\xe2\xec\xc4\x73\x0a\xe2\x0f\x5e\x76\x29\xf6\xde\x72\x1f\x98\x42\x9a\x1a\x61\xb0\xa6\x5b\xb0\xda\x73\x64\x7f\xb3\xa0\x17\xcb\xc1\x74\x21\x8d\x26\xdb\x1d\x80\x65\xa0\xd2\xc6\x77\x32\xf3\xaa\x6a\xd0\xd9\x2d\xe0\x5b\x43\xe3\xa1\xeb\x21\x5d\xaa\x34\x51\xb8\xbf\x72\x55\xeb\x51\xb1\x89\x2b\x6a\xe2\xb6\xb2\x0a\xb7\xf7\x0b\x5a\xdf\xeb\xb5\x85\xeb\x4c\xd5\x9d\xe7\x8a\x04\xe5\x15\x12\xe8\xb7\xd0\xe9\x0a\xa1\x05\xae\xde\x49\x9f\x93\xa3\x8a\xae\x3b\x2c\x48\xa1\x42\x2c\x53\x5e\x95\x14\xec\xa5\x55\x56\x6e\x07\xeb\x0e\x44\xd0\xdc\xc4\x93\x92\x2b\xe6\xbf\xa3\x79\xd1\xa0\x7f\x92\x24\x1d\x1a\xd9\xcf\xe1\x0d\x77\xf0\xc7\x53\xd9\x99\x6b\xd9\x41\x87\x48\xcf\x47\x7b\xf4\xd1\x8b\xea\xf6\xf6\xa6\x15\xff\xff\xef\x7b\x74\xcb\x8f\xe8\x15\x9c\xbd\x76\x95\x2e\x26\x45\x37\x5a\xfc\xe9\xd8\xe6\x25\xf6\xf6\x2f\xfd\xc9\x71\x3a\xb1\x93\xc6\x33\xb3\xe1\xab\x29\xec\x99\x69\x04\x4f\xd2\x0a\x9f\xb8\xb6\x23\xae\xb8\x8e\x33\xbd\x61\xed\x29\xe1\xda\xe2\x08\xea\xaa\xba\xb2\x65\x34\x01\x90\x72\x39\x31\x2a\xd4\xce\x88\xa0\x64\x6a\x5a\x49\xc3\x69\x98\x52\x0d\x55\xd3\xd3\x14\xc5\xa8\xc0\xe6\xad\x99\x56\xe9\xec\x85\x57\xee\xa1\xcc\xa7\xa9\x0a\xda\x74\x61\x7a\x95\x8f\x95\xac\xe8\x2c\x7f\x58\xae\xa2\x52\xa4\xf6\xc4\xca\x0f\xe1\xe3\xe7\xc3\x68\x7a\xb9\x88\x03\x30\x2d\x96\xa6\x84\x58\xba\xa5\x92\x20\x1a\xbe\x89\x4b\x52\xcc\xf1\x89\xa4\xa6\xff\x93\xb0\x37\xce\xa5\xe4\xb7\xf3\x7c\x54\x5c\x44\x8c\x9e\x5c\x4a\x1b\x63\x83\xd1\x0e\x73\x49\xac\xcc\x81\xa2\xbe\xf2\x76\x70\xdf\x4c\x59\x31\xbb\x50\x2f\x51\x40\x96\xb4\xa1\x8f\x12\xba\x0c\x30\x0c\xc1\xca\xf5\xa9\xab\xa7\x75\x06\x82\x6b\x83\xde\xa9\xc3\x34\xae\x46\x24\xae\xc3\xeb\x2b\xdb\x32\x63\x47\x32\x89\x2e\xf3\x42\x39\x0b\x39\x98\xa0\x7d\x92\x20\x5a\xf9\x88\xf6\x1e\xef\x43\x71\x0d\xe5\x2f\x40\x37\x7c\x35\x8e\x71\x86\x77\x6a\xc1\x09\x53\x02\x6e\xe2\x8a\xa2\x7f\x5f\xd0\x84\xe6\x40\xda\xd4\x60\xd0\xef\xda\x3b\xa6\x1f\x65\x45\x0c\x78\xa6\xd9\x55\xf0\xa4\x9c\x8f\xd5\x45\x4d\xa9\xa7\xe3\xac\x91\xae\x82\x76\xe5\xba\xba\x5c\xb2\x60\x84\x4a\xce\x46\xea\xac\x0c\xcc\x00\x47\xab\x69\x3a\xca\x36\x9d\x35\x82\xb2\x72\x04\x36\x0b\x95\x58\xd6\x70\x6c\x3e\xca\xc4\x68\xd2\xe8\x03\xdb\x6a\x57\xd0\x2b\xad\x68\x36\x80\x16\x50\x61\x55\x01\x2e\x05\xbd\xa3\xcc\x1d\x73\xb1\x90\x8d\xf5\x36\xa8\x59\x94\x08\x57\xd5\x62\xd8\x16\xa0\x98\x42\xf2\x07\xfa\x6c\xbe\x17\x81\x92\x92\x1f\x2f\x52\x09\x65\x71\xee\x6f\x92\x1f\xc5\x69\x6a\x0b\xe0\x22\x3e\x00\x38\x5f\xdb\x24\xa0\x7a\x74\xeb\x11\x29\xd5\xc6\x86\xa3\x7e\xfd\x1f\x72\x9e\x7c\xd4\xc8\x8e\xf8\x6c\xfa\x88\x85\xad\x58\x5f\x38\x9c\x6b\xa7\x4b\x23\x0e\x94\xe3\xac\xeb\x3b\x1a\x19\x46\xf4\x1e\xa9\xed\x79\xac\x71\x7c\xac\x71\x0c\x6a\x1c\x4d\xfe\x3a\x93\x0d\xb7\x65\xf9\x6b\xcc\xde\x71\x7d\xea\x1b\xf3\x00\x48\x78\xc0\xdb\xd7\x37\x36\x05\x5e\x8c\xf4\x0e\xae\x92\xcc\x0a\x7d\x5c\x4e\x58\x2c\x96\xfc\xf3\xd6\x05\x26\x75\x7e\x56\x8e\xf2\x6a\xbb\xc4\xf7\xbe\xae\x2f\xde\x65\xf2\x59\x6f\x6e\x06\xd8\xb9\x02\x76\xbe\xa9\x2a\x80\x3a\x0c\xd0\x34\x5d\xdc\x49\x75\x83\x1a\xe1\xa8\xd1\x21\x1e\x6e\xe5\xaa\x86\x5f\x37\xb8\x71\x07\x66\x02\xbd\xf4\x09\x6b\x06\x07\x84\xa7\xb8\x5d\x53\x20\x61\x74\x92\x5f\xb1\xde\xf9\x79\x9a\x28\xe6\x9e\x85\x60\x3b\xa9\x1c\xe3\xb9\x8c\xb1\xde\xbf\xa2\xd2\xbf\x95\x42\xa9\x37\x03\x57\xa0\xd2\x45\xf6\x88\x18\xd1\xc1\x55\x4c\xc3\x28\x23\xa5\x89\xa7\xdd\xe7\xde\x0b\x3f\xa4\xcc\x66\xe2\x0a\x2c\x54\xf3\xb4\x09\xe4\xec\x5e\xd8\xe7\x1c\x93\xfc\xe1\x52\xe0\xb2\xfe\x37\xd7\xee\x9c\xa0\xfa\x1d\x0c\x61\xa2\x23\xc8\x14\x17\x8c\xc8\x46\xa9\xcc\xe0\x00\xee\x97\xb7\x23\x2d\xfb\x0f\xdd\xfb\xfd\x5f\x14\x1b\x7e\x6d\xe3\xc0\x63\x17\x08\x1e\x47\x47\x06\x4d\xf8\x67\x0c\xb0\x77\x3c\x57\xd7\xa2\x84\x9b\x42\x7d\x5a\x07\xab\x0b\x5c\x32\xb7\x7f\x64\xae\xdd\x19\x93\x0f\xcd\x67\xa3\x37\x4e\x0a\x69\xa6\xe9\xb5\xcf\xf1\x72\x34\xb9\x92\xa4\xb1\xfc\x3b\x96\x6b\x2b\x1e\xa9\xa6\xc0\xdb\x2f\x84\x3e\x93\xfa\x24\x4e\x9c\xf8\xbf\x7c\x17\x39\x1a\x36\x1b\x9c\x4e\xce\x29\x67\x36\x1c\xa2\xac\xcb\x50\x58\x9c\xc3\x31\x68\xda\xe3\xfa\x7c\x4e\xea\x43\xa4\xc7\x4b\xeb\x1d\x2e\x40\x99\xdc\xe0\xc3\x64\x28\xd8\xd6\x29\xad\xa6\xfd\x24\x29\xea\x3b\x49\x98\xa2\x3e\x87\xcb\x53\x08\x68\x2f\x91\xca\x6f\x3a\x7c\x02\xb9\xea\x77\xcd\x0a\xa2\xb5\xff\x7e\xc7\xa7\xc5\x5a\xdb\x91\x18\x73\x6f\xbb\x65\x24\x13\x9f\x6c\xb6\x70\xc1\x36\xee\x4e\xa0\x1f\xe2\xa4\x7a\xe2\x1e\x85\x4a\xaf\x9c\xf8\xfe\xc4\x7b\x10\x2a\x61\xfe\xe7\x49\x8c\xdf\xb4\x5b\xdc\x90\xf8\xb2\x9d\x72\x3e\xdc\xff\x35\x9a\xe5\x2e\x4b\x75\x7f\x46\x42\x8a\xd1\x2b\xa5\x1a\xbf\x91\xeb\x9e\xcf\xfe\x65\xb1\xb8\x85\xe5\x79\x6e\xe2\x83\xd1\x58\xdf\xd7\xdf\x1b\xd7\xd3\x2d\x29\xf0\x17\x2b\xdc\xde\x19\x0f\xae\x2f\xc4\x45\x71\x2a\x32\x0e\x98\x37\xea\x2c\xce\x0f\x71\x91\xef\xec\x5f\xd2\xff\x71\x9b\x25\xbd\xe7\x36\xb4\x36\xbd\xa2\xbe\x29\xcb\xb3\x54\xdb\xe7\x34\x62\x40\xd1\x68\xa0\xc1\xaa\x3d\x53\x13\x59\x19\x92\x24\xd4\x30\x8e\x34\x33\x49\x4d\xe3\x39\xab\xd1\x9e\x0c\x56\xe6\x45\x48\x04\x25\x20\xcf\xe7\x25\x5a\xf6\x94\x2c\x3a\x6f\x8a\xc5\x5c\xf9\x9c\xe1\x75\x6a\x25\xbe\xa9\x50\xe6\x07\xd8\xe5\x0f\x95\xfd\xc9\x18\xa5\x26\x73\x30\x53\xa2\xa2\xd2\x98\x47\x83\xf5\xa5\xc3\x0c\x8d\x88\x6c\x0e\x72\x0d\xd5\x62\x8e\x31\x78\x63\x6b\x7f\x93\xfb\xf7\x4a\xe5\xe2\x59\xc6\xdb\x12\xe2\x47\xee\x4f\xe1\x60\x81\x5a\x23\xf9\x18\xc3\x31\x66\xcb\xb1\x8d\x87\x8a\x6e\xc3\x07\xaa\x06\x70\xc9\x00\x9a\x7b\x97\x55\x92\x61\x68\x00\x8b\x53\x17\xbb\xeb\xdb\x4a\x24\x3a\xa7\x61\x9e\x4b\xe7\xf8\x4d\x42\x79\x01\xee\x70\x57\x98\x1d\xb3\x9b\x37\xa1\x18\x49\xa0\xb0\x5c\xea\x5b\x27\x9b\x7b\x24\xf4\xc5\x95\x08\xf3\x7d\xd4\x89\x9d\xd9\xa3\x54\x4d\x91\xaa\x02\xb5\xb2\x89\xa8\x18\xdc\xc0\xc9\xc2\x11\xa9\x34\x87\x7a\xad\x26\x51\xb7\x60\x7a\xc9\x9b\x22\x83\x99\xee\xe7\xce\x26\x3c\x72\xb7\xc8\xdd\x22\xa9\xa6\xb2\x46\xdd\xf9\xa5\x31\x94\x91\xaf\x77\x96\xe7\x0b\x97\x1f\xd7\x77\xd7\xca\x97\x61\xd0\x6c\x2f\xf5\x31\xe5\xb1\xfd\xa9\x0c\x9b\x88\x73\xd7\x40\x0d\xb2\xdb\x8c\x7f\xd5\x34\xb3\x47\xd6\x7a\x1e\x9a\x47\x96\xb1\xad\x0c\xb3\x03\x1b\x2a\xda\x05\x56\x37\xb9\x25\x3c\x4b\x6f\xec\x32\x7b\x1d\x35\x05\xbd\x6f\x6e\x97\x7c\xa0\xf4\x03\x38\xda\x00\x84\x0a\xfe\x2c\x46\x40\x6a\xfa\x8a\xb6\x9c\xd4\x60\xae\x04\xe7\x82\x34\x4d\x64\x23\x2c\x3e\xa4\x45\x02\xd8\xda\x15\xe4\xd9\xa3\xd0\xbc\x5a\x41\xbd\x69\xca\xf2\xd3\xdf\x5d\xf0\xe8\x68\x78\xb3\x3b\xd4\xcd\x94\x7d\xdd\xd6\x9e\xb9\x29\xf8\xe2\xd9\x88\xb0\x8e\xf0\xc0\x68\xa3\x27\x13\xaf\x42\x89\x86\x1f\x17\x7f\xed\xf8\x44\x77\xd4\x04\x1b\xb9\x41\x3f\x9d\x12\xb4\x52\xce\x33\xbe\xcd\xa8\xb0\x3d\xfa\x1f\xee\x2f\x96\x8c\x98\x9b\xd3\x24\x67\xd8\x45\x79\xe2\xcb\x00\x1a\x4e\x7b\xe5\x2a\x3b\x33\xdb\x1e\x83\x99\xb0\xb8\x70\x33\x49\x86\x25\xa9\xdb\xc7\x7c\xd8\xc3\xf2\x61\x7b\x15\x89\x26\xab\xe0\xa1\x49\x31\xb7\x79\xf6\xfb\x65\xc6\xfa\x83\x18\xc3\xc9\x31\xeb\x3c\x15\xcb\x13\x3c\xc3\x5d\x54\x53\x16\xc8\xe7\x90\x75\xc9\xd3\xf6\x63\xa9\xa9\x7e\xdb\xf3\x8f\xc9\xbf\x78\x5b\x3b\xcf\xe7\x29\xd9\xad\x12\x3c\x3c\x1b\x73\xdd\xef\x6a\x87\xe2\xe0\xdc\x2d\x1b\x5c\x2d\x36\xd5\x3b\x18\x97\x89\xcf\xc6\x4f\xfa\x9c\x04\x63\x0f\xe6\x1e\x96\xa2\x71\x6c\x4c\x92\x34\x37\x81\x1f\x62\x6e\x60\x0e\xbd\x10\x3f\x9b\x22\x56\xc0\x61\x34\x93\x53\x62\xfe\x67\xe3\xb7\xfc\x49\x99\xff\x87\x66\x52\xfc\x68\x7d\x24\x49\xf6\x19\xe5\x50\xfe\x64\x9c\x3e\x34\xa5\xe2\x02\x88\x42\x1c\x9e\xc4\x24\x41\xef\x09\x01\xf8\xc4\xc8\xe4\x51\xbd\x67\xf8\xfe\x10\xbb\x5f\x0c\x53\x27\x08\xd3\xc4\xb8\x78\x6a\x84\x3b\x2e\x54\xfb\x06\xba\xa1\x59\x09\x3a\x47\xe9\x1b\x27\xd6\x0f\x4e\xd4\x3c\xda\xa0\x8c\x84\x1e\x16\x45\x67\x85\xed\xb0\x50\xba\x74\xd0\x3b\xfc\xc2\x46\xda\x36\x73\xd2\xfa\xaa\xb6\xc5\xd8\xe9\x11\xeb\x10\x9c\x16\x0c\xec\xda\x87\x8c\xe2\xfe\x77\xa8\x92\xd3\x90\x41\xd3\x4d\xf8\xc9\xa9\xe1\xc6\x8a\x96\xea\x9a\xc6\xdf\x2f\x36\x8e\xb3\x14\xb7\xf1\x87\x5c\xf4\xad\x13\x3a\x98\x53\x37\x41\xba\xa6\xea\x03\x01\xf6\x3c\x02\x61\x99\x4f\x31\x14\x97\x9d\xec\xbe\xa4\xcc\x95\x4d\xfb\xa7\x6f\xd2\xb4\x47\x78\xda\x3a\xfa\x02\xd0\x79\xc8\xc6\x40\x35\x7c\x8f\xbb\x4e\x95\xd8\x2d\xe3\x03\x6c\x2a\x6c\x1d\x0c\xe6\x09\x24\x5e\x4b\x9f\x2b\xb1\x9f\xee\x38\x47\xef\x1d\x0b\x7f\x27\x0e\x7d\x88\x52\x26\xd9\xa3\x16\xee\x53\x22\x97\xe8\x7d\xf1\x20\xc9\x55\x5d\x9b\x1a\x5c\xd3\xfc\x0b\x9e\xff\xa4\x56\xf4\x45\x1b\x14\x7e\x49\x83\xa9\x6b\xf0\xfe\x4f\xaf\x17\xf9\x37\xc0\x85\x7f\xe6\x26\xf8\xb3\xb5\xe7\x57\x6e\x11\xd9\x3f\x75\x73\xd3\xe8\xc7\xec\x72\x40\x4f\x52\x38\x13\x3e\x6a\x97\x27\x6a\xd1\xb8\xff\x17\xf8\x9f\x56\xe2\x39\xf1\xc8\xdc\x0e\x61\x39\x9f\x7c\x4a\xef\x77\xe3\xcd\xd0\xd5\x2c\x8e\x35\x06\x9d\x9f\x07\xd2\x6d\x6e\x16\xba\x6e\x3d\xd2\x37\xea\xc6\x93\x9c\x22\x2a\x9d\x67\x31\xd5\xef\xb9\x2e\xb3\x09\x36\x6e\xec\x86\x90\xe0\x93\x52\x03\x57\x85\xe0\xba\xee\xe9\x3e\xab\x70\x97\xf2\x21\xa0\x77\xbc\xa0\x9f\xe6\x26\x10\xdb\x8f\xf8\xfb\x5b\xdc\x7d\xe6\x8c\x70\x7f\x26\xa1\xc5\xb0\x9d\x49\x8b\x28\x33\x5f\xd5\x5c\x00\xb2\x27\xd4\xfa\x23\x19\xe9\x07\x93\x92\x4a\x8c\x81\xef\xf4\x84\x33\x3a\x1f\x20\xe3\x69\xc1\xa6\xa4\x76\xc0\x35\xeb\x69\xf9\x51\xe8\x1a\xdf\xb4\x90\xd7\xfa\x99\xd1\x51\x31\x69\xfb\x89\x04\x62\x52\xb2\xbd\xc2\xdd\x68\xcd\x69\xfc\xd9\xc0\x7d\xf2\xec\x05\xca\x54\xb8\x1b\xa0\xcc\x88\x09\xdb\xc3\x6a\x45\x7f\x7b\x19\xb1\xe8\xef\x53\xd8\xb4\xf8\xf4\xd0\x40\x49\x7f\x96\xb0\x83\x45\xfd\x26\xf4\xc0\x75\x7f\x22\x5f\xdf\x9f\x19\x7f\x44\x6d\x85\xb9\x3d\x6b\x0a\x75\x70\x19\x9b\x56\x00\x2c\xfe\xdc\x5e\x7a\x97\x66\x4f\xac\x44\xba\xf2\xc8\x05\x12\x17\x7f\x6c\x6f\xf4\xaa\x7c\x85\xb7\x17\xe8\xe5\x88\xf3\xa4\x18\xf1\x99\xce\xf3\x51\x11\xcb\x3d\x3d\x48\xde\xf2\xcf\x27\x8b\x5f\xff\xff\x81\x5d\x4e\x63\x87\xfc\xdb\x34\x82\xe3\x5f\x5a\xfe\xb4\x35\x44\xfe\xd6\x97\xec\x1c\xdc\x31\x2f\x5b\x17\xbe\x1e\x9d\x68\xfa\xde\x5a\xa7\xf2\xfd\xf0\x0f\x27\x9d\xa3\xaf\x06\x6f\xdb\xe8\x8f\xae\x9a\xa9\x96\x91\x50\xff\xc4\x46\x53\x1f\xa8\xb4\xb7\x1f\xfb\x77\xc5\x3b\x0b\xe6\xee\x29\x28\x5c\xc5\xe4\xee\x3f\x0c\xbe\x16\xa6\x8d\xaf\x33\xb7\xc9\xa7\xae\x07\xe8\xe8\x61\xf1\x07\x5f\xf3\x63\xdd\x2d\x43\x92\x01\xb2\x0f\xe0\x1c\xfc\x8c\x31\x4f\xcf\x02\x66\xfc\xb0\x58\xc4\x42\x6b\x31\xeb\x85\x24\x7c\x91\xc3\x37\x90\x92\x18\x8e\x3f\xbe\x32\xfd\x58\xaf\x3e\x45\x53\x73\xe5\xc5\x09\x7a\x7a\x65\xef\x97\xe9\xe1\x2b\x1d\x34\xf8\x4d\x63\x74\x89\xce\xcc\x6d\x26\x67\x4d\xf9\x4e\xaf\x02\x20\xef\x73\xbf\x12\x90\xf9\xd8\x70\x0e\x50\x11\x52\xfc\x0d\xe1\x02\x9c\x30\x44\xca\x02\xc9\x7e\x02\xb8\x30\xbf\xa8\x43\x84\x9e\x27\x35\x05\x50\x4b\xab\x10\xfe\x11\x7e\x15\xd0\x43\x2c\xfb\x7d\x5d\x35\x3b\xf5\xeb\xac\x89\x5b\x65\x69\x54\xfc\xf4\x6d\x3a\xb1\x28\xdd\x35\x0a\x6c\x1c\xab\x20\x73\x66\x75\x8a\xd3\xdd\x9c\xb4\x77\x4d\xfa\x2d\x67\x55\x74\x69\xd4\x8c\x97\xf3\x57\x26\xd8\x20\x3c\xe7\x78\x0b\xb3\x91\x38\x48\x2e\xc9\xf3\x3d\x38\x6d\x97\xc9\x87\xa3\xff\x09\x00\x00\xff\xff\x06\xa9\x9c\x6c\xfd\x83\x00\x00" func lockedtokensCdcBytes() ([]byte, error) { @@ -481,6 +502,7 @@ var _bindata = map[string]func() (*asset, error){ "FlowStakingCollection.cdc": flowstakingcollectionCdc, "FlowStorageFees.cdc": flowstoragefeesCdc, "FlowToken.cdc": flowtokenCdc, + "LinearCodeAddressGenerator.cdc": linearcodeaddressgeneratorCdc, "LockedTokens.cdc": lockedtokensCdc, "NodeVersionBeacon.cdc": nodeversionbeaconCdc, "RandomBeaconHistory.cdc": randombeaconhistoryCdc, @@ -544,6 +566,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "FlowStakingCollection.cdc": {flowstakingcollectionCdc, map[string]*bintree{}}, "FlowStorageFees.cdc": {flowstoragefeesCdc, map[string]*bintree{}}, "FlowToken.cdc": {flowtokenCdc, map[string]*bintree{}}, + "LinearCodeAddressGenerator.cdc": {linearcodeaddressgeneratorCdc, map[string]*bintree{}}, "LockedTokens.cdc": {lockedtokensCdc, map[string]*bintree{}}, "NodeVersionBeacon.cdc": {nodeversionbeaconCdc, map[string]*bintree{}}, "RandomBeaconHistory.cdc": {randombeaconhistoryCdc, map[string]*bintree{}}, diff --git a/tests/LinearCodeAddressGenerator_test.cdc b/tests/LinearCodeAddressGenerator_test.cdc new file mode 100644 index 00000000..8f53016a --- /dev/null +++ b/tests/LinearCodeAddressGenerator_test.cdc @@ -0,0 +1,166 @@ +import Test +import "LinearCodeAddressGenerator" + +access(all) +fun setup() { + var err: Test.Error? = Test.deployContract( + name: "LinearCodeAddressGenerator", + path: "../contracts/LinearCodeAddressGenerator.cdc", + arguments: [], + ) + Test.expect(err, Test.beNil()) +} + +access(all) +fun generateAddresses( + count: UInt64, + chain: LinearCodeAddressGenerator.Chain +): [Address] { + let addresses: [Address] = [] + for index in InclusiveRange(1, count) { + let address = LinearCodeAddressGenerator.address( + at: index, + chain: chain + ) + addresses.append(address!) + } + + return addresses +} + +access(all) +fun checkAddresses( + count: UInt64, + chain: LinearCodeAddressGenerator.Chain, + expected: [Address] +) { + let actual = generateAddresses( + count: 10, + chain: chain + ) + + Test.assertEqual(expected, actual) + + for address in actual { + Test.assert( + LinearCodeAddressGenerator.isValidAddress( + address, + chain: chain + ) + ) + + for otherChain in [ + LinearCodeAddressGenerator.Chain.Mainnet, + LinearCodeAddressGenerator.Chain.Testnet, + LinearCodeAddressGenerator.Chain.Transient + ] { + if otherChain == chain { + continue + } + + Test.assert( + !LinearCodeAddressGenerator.isValidAddress( + address, + chain: otherChain + ) + ) + } + } +} + +access(all) +fun testMainnet() { + checkAddresses( + count: 10, + chain: LinearCodeAddressGenerator.Chain.Mainnet, + expected: [ + 0xe467b9dd11fa00df, + 0xf233dcee88fe0abe, + 0x1654653399040a61, + 0xf919ee77447b7497, + 0x1d7e57aa55817448, + 0x0b2a3299cc857e29, + 0xef4d8b44dd7f7ef6, + 0xfc8cf73ba23a260d, + 0x18eb4ee6b3c026d2, + 0x0ebf2bd52ac42cb3 + ] + ) +} + +access(all) +fun testTestnet() { + checkAddresses( + count: 10, + chain: LinearCodeAddressGenerator.Chain.Testnet, + expected: [ + 0x8c5303eaa26202d6, + 0x9a0766d93b6608b7, + 0x7e60df042a9c0868, + 0x912d5440f7e3769e, + 0x754aed9de6197641, + 0x631e88ae7f1d7c20, + 0x877931736ee77cff, + 0x94b84d0c11a22404, + 0x70dff4d1005824db, + 0x668b91e2995c2eba + ] + ) +} + +access(all) +fun testTransient() { + checkAddresses( + count: 10, + chain: LinearCodeAddressGenerator.Chain.Transient, + expected: [ + 0xf8d6e0586b0a20c7, + 0xee82856bf20e2aa6, + 0x0ae53cb6e3f42a79, + 0xe5a8b7f23e8b548f, + 0x01cf0e2f2f715450, + 0x179b6b1cb6755e31, + 0xf3fcd2c1a78f5eee, + 0xe03daebed8ca0615, + 0x045a1763c93006ca, + 0x120e725050340cab + ] + ) +} + +access(all) +fun testAddressAtIndex() { + + let minIndex: UInt64 = 1 + let maxIndex: UInt64 = 35184372088831 + + for chain in [ + LinearCodeAddressGenerator.Chain.Mainnet, + LinearCodeAddressGenerator.Chain.Testnet, + LinearCodeAddressGenerator.Chain.Transient + ] { + let lessThanMinAddress = LinearCodeAddressGenerator.address( + at: minIndex - 1, + chain: chain + ) + Test.assert(lessThanMinAddress == nil) + + let minAddress = LinearCodeAddressGenerator.address( + at: minIndex, + chain: chain + ) + Test.assert(minAddress != nil) + + let maxAddress = LinearCodeAddressGenerator.address( + at: maxIndex, + chain: chain + ) + Test.assert(maxAddress != nil) + + let greaterThanMaxAddress = LinearCodeAddressGenerator.address( + at: maxIndex + 1, + chain: chain + ) + Test.assert(greaterThanMaxAddress == nil) + } +} \ No newline at end of file