mirror of
https://github.com/luxfi/coreth.git
synced 2026-10-30 17:00:51 +00:00
139 lines
3.8 KiB
Go
139 lines
3.8 KiB
Go
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package modules
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"sort"
|
|
|
|
"github.com/luxfi/coreth/precompile/contract"
|
|
"github.com/luxfi/geth/common"
|
|
)
|
|
|
|
type Module struct {
|
|
// ConfigKey is the key used in json config files to specify this precompile config.
|
|
ConfigKey string
|
|
// Address returns the address where the stateful precompile is accessible.
|
|
Address common.Address
|
|
// Contract returns a thread-safe singleton that can be used as the StatefulPrecompiledContract when
|
|
// this config is enabled.
|
|
Contract contract.StatefulPrecompiledContract
|
|
// Configurator is used to configure the stateful precompile when the config is enabled.
|
|
contract.Configurator
|
|
}
|
|
|
|
type moduleArray []Module
|
|
|
|
func (u moduleArray) Len() int {
|
|
return len(u)
|
|
}
|
|
|
|
func (u moduleArray) Swap(i, j int) {
|
|
u[i], u[j] = u[j], u[i]
|
|
}
|
|
|
|
func (m moduleArray) Less(i, j int) bool {
|
|
return bytes.Compare(m[i].Address.Bytes(), m[j].Address.Bytes()) < 0
|
|
}
|
|
|
|
var (
|
|
// registeredModules is a list of Module to preserve order
|
|
// for deterministic iteration
|
|
registeredModules = make([]Module, 0)
|
|
|
|
// BlackholeAddr is the address of the blackhole
|
|
BlackholeAddr = common.HexToAddress("0x0100000000000000000000000000000000000000")
|
|
|
|
reservedRanges = []AddressRange{
|
|
{
|
|
Start: common.HexToAddress("0x0100000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x01000000000000000000000000000000000000ff"),
|
|
},
|
|
{
|
|
Start: common.HexToAddress("0x0200000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x02000000000000000000000000000000000000ff"),
|
|
},
|
|
{
|
|
Start: common.HexToAddress("0x0300000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x03000000000000000000000000000000000000ff"),
|
|
},
|
|
}
|
|
)
|
|
|
|
// AddressRange represents a contiguous range of addresses
|
|
type AddressRange struct {
|
|
Start common.Address
|
|
End common.Address
|
|
}
|
|
|
|
// Contains returns true if the address is contained in the range
|
|
func (a AddressRange) Contains(addr common.Address) bool {
|
|
addrBytes := addr.Bytes()
|
|
return bytes.Compare(addrBytes, a.Start.Bytes()) >= 0 && bytes.Compare(addrBytes, a.End.Bytes()) <= 0
|
|
}
|
|
|
|
// ReservedAddress returns true if [addr] is in a reserved range for custom precompiles
|
|
func ReservedAddress(addr common.Address) bool {
|
|
for _, reservedRange := range reservedRanges {
|
|
if reservedRange.Contains(addr) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// RegisterModule registers a stateful precompile module
|
|
func RegisterModule(stm Module) error {
|
|
address := stm.Address
|
|
key := stm.ConfigKey
|
|
|
|
if address == BlackholeAddr {
|
|
return fmt.Errorf("address %s overlaps with blackhole address", address)
|
|
}
|
|
if !ReservedAddress(address) {
|
|
return fmt.Errorf("address %s not in a reserved range", address)
|
|
}
|
|
|
|
for _, registeredModule := range registeredModules {
|
|
if registeredModule.ConfigKey == key {
|
|
return fmt.Errorf("name %s already used by a stateful precompile", key)
|
|
}
|
|
if registeredModule.Address == address {
|
|
return fmt.Errorf("address %s already used by a stateful precompile", address)
|
|
}
|
|
}
|
|
// sort by address to ensure deterministic iteration
|
|
registeredModules = insertSortedByAddress(registeredModules, stm)
|
|
return nil
|
|
}
|
|
|
|
func GetPrecompileModuleByAddress(address common.Address) (Module, bool) {
|
|
for _, stm := range registeredModules {
|
|
if stm.Address == address {
|
|
return stm, true
|
|
}
|
|
}
|
|
return Module{}, false
|
|
}
|
|
|
|
func GetPrecompileModule(key string) (Module, bool) {
|
|
for _, stm := range registeredModules {
|
|
if stm.ConfigKey == key {
|
|
return stm, true
|
|
}
|
|
}
|
|
return Module{}, false
|
|
}
|
|
|
|
func RegisteredModules() []Module {
|
|
return registeredModules
|
|
}
|
|
|
|
func insertSortedByAddress(data []Module, stm Module) []Module {
|
|
data = append(data, stm)
|
|
sort.Sort(moduleArray(data))
|
|
return data
|
|
} |