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