github.com/onflow/flow-go@v0.33.17/model/flow/address.go (about)

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