github.com/MetalBlockchain/subnet-evm@v0.4.9/precompile/utils.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  	"regexp"
     9  
    10  	"github.com/MetalBlockchain/subnet-evm/vmerrs"
    11  	"github.com/ethereum/go-ethereum/common"
    12  	"github.com/ethereum/go-ethereum/crypto"
    13  )
    14  
    15  var functionSignatureRegex = regexp.MustCompile(`[\w]+\(((([\w]+)?)|((([\w]+),)+([\w]+)))\)`)
    16  
    17  // CalculateFunctionSelector returns the 4 byte function selector that results from [functionSignature]
    18  // Ex. the function setBalance(addr address, balance uint256) should be passed in as the string:
    19  // "setBalance(address,uint256)"
    20  func CalculateFunctionSelector(functionSignature string) []byte {
    21  	if !functionSignatureRegex.MatchString(functionSignature) {
    22  		panic(fmt.Errorf("invalid function signature: %q", functionSignature))
    23  	}
    24  	hash := crypto.Keccak256([]byte(functionSignature))
    25  	return hash[:4]
    26  }
    27  
    28  // deductGas checks if [suppliedGas] is sufficient against [requiredGas] and deducts [requiredGas] from [suppliedGas].
    29  func deductGas(suppliedGas uint64, requiredGas uint64) (uint64, error) {
    30  	if suppliedGas < requiredGas {
    31  		return 0, vmerrs.ErrOutOfGas
    32  	}
    33  	return suppliedGas - requiredGas, nil
    34  }
    35  
    36  // packOrderedHashesWithSelector packs the function selector and ordered list of hashes into [dst]
    37  // byte slice.
    38  // assumes that [dst] has sufficient room for [functionSelector] and [hashes].
    39  func packOrderedHashesWithSelector(dst []byte, functionSelector []byte, hashes []common.Hash) {
    40  	copy(dst[:len(functionSelector)], functionSelector)
    41  	packOrderedHashes(dst[len(functionSelector):], hashes)
    42  }
    43  
    44  // packOrderedHashes packs the ordered list of [hashes] into the [dst] byte buffer.
    45  // assumes that [dst] has sufficient space to pack [hashes] or else this function will panic.
    46  func packOrderedHashes(dst []byte, hashes []common.Hash) {
    47  	if len(dst) != len(hashes)*common.HashLength {
    48  		panic(fmt.Sprintf("destination byte buffer has insufficient length (%d) for %d hashes", len(dst), len(hashes)))
    49  	}
    50  
    51  	var (
    52  		start = 0
    53  		end   = common.HashLength
    54  	)
    55  	for _, hash := range hashes {
    56  		copy(dst[start:end], hash.Bytes())
    57  		start += common.HashLength
    58  		end += common.HashLength
    59  	}
    60  }
    61  
    62  // returnPackedHash returns packed the byte slice with common.HashLength from [packed]
    63  // at the given [index].
    64  // Assumes that [packed] is composed entirely of packed 32 byte segments.
    65  func returnPackedHash(packed []byte, index int) []byte {
    66  	start := common.HashLength * index
    67  	end := start + common.HashLength
    68  	return packed[start:end]
    69  }