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  }