github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/evm/handler/addressAllocator.go (about)

     1  package handler
     2  
     3  import (
     4  	"encoding/binary"
     5  
     6  	"github.com/onflow/flow-go/fvm/evm/types"
     7  )
     8  
     9  const (
    10  	// `addressIndexMultiplierConstant` is used for mapping address indices
    11  	// into deterministic random-looking address postfixes.
    12  	// The constant must be an ODD number.
    13  	// It is a "nothing-up-my-sleeves" constant, chosen to be big enough so that
    14  	// the index and its corresponding address look less "related".
    15  	// Note that the least significant byte was set to "77" instead of "88" to force
    16  	// the odd parity.
    17  	// Look at `mapAddressIndex` for more details.
    18  	addressIndexMultiplierConstant = uint64(0xFFEEDDCCBBAA9977)
    19  )
    20  
    21  type AddressAllocator struct {
    22  }
    23  
    24  var _ types.AddressAllocator = &AddressAllocator{}
    25  
    26  // NewAddressAllocator constructs a new statefull address allocator
    27  func NewAddressAllocator() *AddressAllocator {
    28  	return &AddressAllocator{}
    29  }
    30  
    31  func (aa *AddressAllocator) COAFactoryAddress() types.Address {
    32  	return MakeCOAAddress(0)
    33  }
    34  
    35  func (aa *AddressAllocator) NativeTokenBridgeAddress() types.Address {
    36  	return MakePrecompileAddress(0)
    37  }
    38  
    39  // AllocateCOAAddress allocates an address for COA
    40  func (aa *AddressAllocator) AllocateCOAAddress(uuid uint64) types.Address {
    41  	return MakeCOAAddress(uuid)
    42  }
    43  
    44  func MakeCOAAddress(index uint64) types.Address {
    45  	return makePrefixedAddress(mapAddressIndex(index), types.FlowEVMCOAAddressPrefix)
    46  }
    47  
    48  func (aa *AddressAllocator) AllocatePrecompileAddress(index uint64) types.Address {
    49  	target := MakePrecompileAddress(index)
    50  	return target
    51  }
    52  
    53  func MakePrecompileAddress(index uint64) types.Address {
    54  	return makePrefixedAddress(index, types.FlowEVMExtendedPrecompileAddressPrefix)
    55  }
    56  
    57  func makePrefixedAddress(
    58  	index uint64,
    59  	prefix [types.FlowEVMSpecialAddressPrefixLen]byte,
    60  ) types.Address {
    61  	var addr types.Address
    62  	copy(addr[:], prefix[:])
    63  	// only works if `len(addr) - len(prefix)` is exactly 8 bytes
    64  	binary.BigEndian.PutUint64(addr[len(prefix):], index)
    65  	return addr
    66  }
    67  
    68  // `mapAddressIndex` maps an index of 64 bits to a deterministic random-looking 64 bits.
    69  //
    70  // The mapping function must be an injective mapping (in this case bijective)
    71  // where every two indices always map to two different results. Multiple injective
    72  // mappings are possible.
    73  //
    74  // The current implementation uses a simple modular multiplication by a constant modulo 2^64.
    75  // The multiplier constant can be any odd number. Since odd numbers are co-prime with 2^64, they
    76  // have a multiplicative inverse modulo 2^64.
    77  // This makes multiplying by an odd number an injective function (and therefore bijective).
    78  //
    79  // Multiplying modulo 2^64 is implicitly implemented as a uint64 multiplication with a uin64 result.
    80  func mapAddressIndex(index uint64) uint64 {
    81  	return uint64(index * addressIndexMultiplierConstant)
    82  }