github.com/algorand/go-algorand-sdk@v1.24.0/types/address.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "crypto/sha512" 6 "encoding/base32" 7 ) 8 9 const ( 10 checksumLenBytes = 4 11 hashLenBytes = sha512.Size256 12 ) 13 14 // Address represents an Algorand address. 15 type Address [hashLenBytes]byte 16 17 // String grabs a human-readable representation of the address. This 18 // representation includes a 4-byte checksum. 19 func (a Address) String() string { 20 // Compute the checksum 21 checksumHash := sha512.Sum512_256(a[:]) 22 checksumLenBytes := checksumHash[hashLenBytes-checksumLenBytes:] 23 24 // Append the checksum and encode as base32 25 checksumAddress := append(a[:], checksumLenBytes...) 26 return base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(checksumAddress) 27 } 28 29 // ZeroAddress is Address with all zero bytes. For handy == != comparisons. 30 var ZeroAddress Address = [hashLenBytes]byte{} 31 32 // IsZero returs true if the Address is all zero bytes. 33 func (a Address) IsZero() bool { 34 return a == ZeroAddress 35 } 36 37 // DecodeAddress turns a checksum address string into an Address object. It 38 // checks that the checksum is correct, and returns an error if it's not. 39 func DecodeAddress(addr string) (a Address, err error) { 40 // Interpret the address as base32 41 decoded, err := base32.StdEncoding.WithPadding(base32.NoPadding).DecodeString(addr) 42 if err != nil { 43 return 44 } 45 46 // Ensure the decoded address is the correct length 47 if len(decoded) != len(a)+checksumLenBytes { 48 err = errWrongAddressLen 49 return 50 } 51 52 // Split into address + checksum 53 addressBytes := decoded[:len(a)] 54 checksumBytes := decoded[len(a):] 55 56 // Compute the expected checksum 57 checksumHash := sha512.Sum512_256(addressBytes) 58 expectedChecksumBytes := checksumHash[hashLenBytes-checksumLenBytes:] 59 60 // Check the checksum 61 if !bytes.Equal(expectedChecksumBytes, checksumBytes) { 62 err = errWrongChecksum 63 return 64 } 65 66 // Checksum is good, copy address bytes into output 67 copy(a[:], addressBytes) 68 return a, nil 69 } 70 71 // EncodeAddress turns a byte slice into the human readable representation of the address. 72 // This representation includes a 4-byte checksum 73 func EncodeAddress(addr []byte) (a string, err error) { 74 if len(addr) != hashLenBytes { 75 err = errWrongAddressByteLen 76 return 77 } 78 79 var address Address 80 copy(address[:], addr) 81 a = address.String() 82 83 return 84 }