address.gno
2.20 Kb · 54 lines
1package connect4
2
3// The chain decodes four texts to the same address: the bech32 form it gives
4// a caller, that form in capitals, and the bech32m checksum in either case.
5// An address argument stored as text and later compared with a caller's
6// address must be that first form. canonical reads the text itself, which
7// costs far less gas than decoding and re-encoding it. It is the check of
8// gno.land/p/samcrew/launchpad/meta/v1 (ValidAddress), copied so this realm
9// does not depend on that package being published.
10
11// bech32Value holds, for each character of the bech32 alphabet
12// "qpzry9x8gf2tvdw0s3jn54khce6mua7l", its 5-bit value plus one. Zero marks
13// every other byte, capitals included.
14var bech32Value = [256]byte{
15 'q': 1, 'p': 2, 'z': 3, 'r': 4, 'y': 5, '9': 6, 'x': 7, '8': 8,
16 'g': 9, 'f': 10, '2': 11, 't': 12, 'v': 13, 'd': 14, 'w': 15, '0': 16,
17 's': 17, '3': 18, 'j': 19, 'n': 20, '5': 21, '4': 22, 'k': 23, 'h': 24,
18 'c': 25, 'e': 26, '6': 27, 'm': 28, 'u': 29, 'a': 30, '7': 31, 'l': 32,
19}
20
21// bech32Gen[t] is the XOR of the BIP-173 generators selected by the five
22// bits of t: one table read per character instead of five tests.
23var bech32Gen = [32]uint32{
24 0x00000000, 0x3b6a57b2, 0x26508e6d, 0x1d3ad9df,
25 0x1ea119fa, 0x25cb4e48, 0x38f19797, 0x039bc025,
26 0x3d4233dd, 0x0628646f, 0x1b12bdb0, 0x2078ea02,
27 0x23e32a27, 0x18897d95, 0x05b3a44a, 0x3ed9f3f8,
28 0x2a1462b3, 0x117e3501, 0x0c44ecde, 0x372ebb6c,
29 0x34b57b49, 0x0fdf2cfb, 0x12e5f524, 0x298fa296,
30 0x1756516e, 0x2c3c06dc, 0x3106df03, 0x0a6c88b1,
31 0x09f74894, 0x329d1f26, 0x2fa7c6f9, 0x14cd914b,
32}
33
34// The checksum state once the address prefix "g" has been absorbed, which
35// BIP-173 expands to the values 3, 0, 7.
36const bech32PrefixState uint32 = 0x8c07
37
38// canonical reports whether a is "g1", then 38 lowercase bech32 characters
39// whose checksum is the original bech32 one: the form a caller's address has.
40func canonical(a address) bool {
41 s := string(a)
42 if len(s) != 40 || s[0] != 'g' || s[1] != '1' {
43 return false
44 }
45 chk := bech32PrefixState
46 for i := 2; i < 40; i++ {
47 v := bech32Value[s[i]]
48 if v == 0 {
49 return false
50 }
51 chk = (chk&0x1ffffff)<<5 ^ uint32(v-1) ^ bech32Gen[chk>>25]
52 }
53 return chk == 1 // 1 is bech32; bech32m ends on 0x2bc830a3
54}