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