github.com/MetalBlockchain/subnet-evm@v0.4.9/precompile/contract.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package precompile
     5  
     6  import (
     7  	"fmt"
     8  	"math/big"
     9  
    10  	"github.com/MetalBlockchain/metalgo/snow"
    11  	"github.com/MetalBlockchain/subnet-evm/commontype"
    12  	"github.com/ethereum/go-ethereum/common"
    13  )
    14  
    15  const (
    16  	selectorLen = 4
    17  )
    18  
    19  type RunStatefulPrecompileFunc func(accessibleState PrecompileAccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error)
    20  
    21  // PrecompileAccessibleState defines the interface exposed to stateful precompile contracts
    22  type PrecompileAccessibleState interface {
    23  	GetStateDB() StateDB
    24  	GetBlockContext() BlockContext
    25  	GetSnowContext() *snow.Context
    26  	CallFromPrecompile(caller common.Address, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error)
    27  }
    28  
    29  // BlockContext defines an interface that provides information to a stateful precompile
    30  // about the block that activates the upgrade. The precompile can access this information
    31  // to initialize its state.
    32  type BlockContext interface {
    33  	Number() *big.Int
    34  	Timestamp() *big.Int
    35  }
    36  
    37  // ChainContext defines an interface that provides information to a stateful precompile
    38  // about the chain configuration. The precompile can access this information to initialize
    39  // its state.
    40  type ChainConfig interface {
    41  	// GetFeeConfig returns the original FeeConfig that was set in the genesis.
    42  	GetFeeConfig() commontype.FeeConfig
    43  	// AllowedFeeRecipients returns true if fee recipients are allowed in the genesis.
    44  	AllowedFeeRecipients() bool
    45  }
    46  
    47  // StateDB is the interface for accessing EVM state
    48  type StateDB interface {
    49  	GetState(common.Address, common.Hash) common.Hash
    50  	SetState(common.Address, common.Hash, common.Hash)
    51  
    52  	SetCode(common.Address, []byte)
    53  
    54  	SetNonce(common.Address, uint64)
    55  	GetNonce(common.Address) uint64
    56  
    57  	GetBalance(common.Address) *big.Int
    58  	AddBalance(common.Address, *big.Int)
    59  	SubBalance(common.Address, *big.Int)
    60  
    61  	CreateAccount(common.Address)
    62  	Exist(common.Address) bool
    63  
    64  	AddLog(addr common.Address, topics []common.Hash, data []byte, blockNumber uint64)
    65  
    66  	Suicide(common.Address) bool
    67  	Finalise(deleteEmptyObjects bool)
    68  }
    69  
    70  // StatefulPrecompiledContract is the interface for executing a precompiled contract
    71  type StatefulPrecompiledContract interface {
    72  	// Run executes the precompiled contract.
    73  	Run(accessibleState PrecompileAccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error)
    74  }
    75  
    76  // statefulPrecompileFunction defines a function implemented by a stateful precompile
    77  type statefulPrecompileFunction struct {
    78  	// selector is the 4 byte function selector for this function
    79  	// This should be calculated from the function signature using CalculateFunctionSelector
    80  	selector []byte
    81  	// execute is performed when this function is selected
    82  	execute RunStatefulPrecompileFunc
    83  }
    84  
    85  // newStatefulPrecompileFunction creates a stateful precompile function with the given arguments
    86  func newStatefulPrecompileFunction(selector []byte, execute RunStatefulPrecompileFunc) *statefulPrecompileFunction {
    87  	return &statefulPrecompileFunction{
    88  		selector: selector,
    89  		execute:  execute,
    90  	}
    91  }
    92  
    93  // statefulPrecompileWithFunctionSelectors implements StatefulPrecompiledContract by using 4 byte function selectors to pass
    94  // off responsibilities to internal execution functions.
    95  // Note: because we only ever read from [functions] there no lock is required to make it thread-safe.
    96  type statefulPrecompileWithFunctionSelectors struct {
    97  	fallback  RunStatefulPrecompileFunc
    98  	functions map[string]*statefulPrecompileFunction
    99  }
   100  
   101  // newStatefulPrecompileWithFunctionSelectors generates new StatefulPrecompile using [functions] as the available functions and [fallback]
   102  // as an optional fallback if there is no input data. Note: the selector of [fallback] will be ignored, so it is required to be left empty.
   103  func newStatefulPrecompileWithFunctionSelectors(fallback RunStatefulPrecompileFunc, functions []*statefulPrecompileFunction) StatefulPrecompiledContract {
   104  	// Construct the contract and populate [functions].
   105  	contract := &statefulPrecompileWithFunctionSelectors{
   106  		fallback:  fallback,
   107  		functions: make(map[string]*statefulPrecompileFunction),
   108  	}
   109  	for _, function := range functions {
   110  		_, exists := contract.functions[string(function.selector)]
   111  		if exists {
   112  			panic(fmt.Errorf("cannot create stateful precompile with duplicated function selector: %q", function.selector))
   113  		}
   114  		contract.functions[string(function.selector)] = function
   115  	}
   116  
   117  	return contract
   118  }
   119  
   120  // Run selects the function using the 4 byte function selector at the start of the input and executes the underlying function on the
   121  // given arguments.
   122  func (s *statefulPrecompileWithFunctionSelectors) Run(accessibleState PrecompileAccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
   123  	// If there is no input data present, call the fallback function if present.
   124  	if len(input) == 0 && s.fallback != nil {
   125  		return s.fallback(accessibleState, caller, addr, nil, suppliedGas, readOnly)
   126  	}
   127  
   128  	// Otherwise, an unexpected input size will result in an error.
   129  	if len(input) < selectorLen {
   130  		return nil, suppliedGas, fmt.Errorf("missing function selector to precompile - input length (%d)", len(input))
   131  	}
   132  
   133  	// Use the function selector to grab the correct function
   134  	selector := input[:selectorLen]
   135  	functionInput := input[selectorLen:]
   136  	function, ok := s.functions[string(selector)]
   137  	if !ok {
   138  		return nil, suppliedGas, fmt.Errorf("invalid function selector %#x", selector)
   139  	}
   140  
   141  	return function.execute(accessibleState, caller, addr, functionInput, suppliedGas, readOnly)
   142  }