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 }