github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/execution/evm/abi/function_spec.go (about)

     1  package abi
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"golang.org/x/crypto/sha3"
     7  )
     8  
     9  // FunctionIDSize is the length of the function selector
    10  const FunctionIDSize = 4
    11  
    12  type FunctionSpec struct {
    13  	Name       string
    14  	FunctionID FunctionID
    15  	Constant   bool
    16  	Inputs     []Argument
    17  	Outputs    []Argument
    18  }
    19  
    20  type FunctionID [FunctionIDSize]byte
    21  
    22  func NewFunctionSpec(name string, inputs, outputs []Argument) *FunctionSpec {
    23  	sig := Signature(name, inputs)
    24  	return &FunctionSpec{
    25  		Name:       name,
    26  		FunctionID: GetFunctionID(sig),
    27  		Constant:   false,
    28  		Inputs:     inputs,
    29  		Outputs:    outputs,
    30  	}
    31  }
    32  
    33  func GetFunctionID(signature string) (id FunctionID) {
    34  	hash := sha3.NewLegacyKeccak256()
    35  	hash.Write([]byte(signature))
    36  	copy(id[:], hash.Sum(nil)[:4])
    37  	return
    38  }
    39  
    40  func Signature(name string, args []Argument) string {
    41  	return name + argsToSignature(args, false)
    42  }
    43  
    44  // Sets this function as constant
    45  func (f *FunctionSpec) SetConstant() *FunctionSpec {
    46  	f.Constant = true
    47  	return f
    48  }
    49  
    50  func (f *FunctionSpec) String() string {
    51  	return f.Name + argsToSignature(f.Inputs, true) +
    52  		" returns " + argsToSignature(f.Outputs, true)
    53  }
    54  
    55  func (fs FunctionID) Bytes() []byte {
    56  	return fs[:]
    57  }
    58  
    59  func argsToSignature(args []Argument, addIndexedName bool) (str string) {
    60  	str = "("
    61  	for i, a := range args {
    62  		if i > 0 {
    63  			str += ","
    64  		}
    65  		str += a.EVM.GetSignature()
    66  		if addIndexedName && a.Indexed {
    67  			str += " indexed"
    68  		}
    69  		if a.IsArray {
    70  			if a.ArrayLength > 0 {
    71  				str += fmt.Sprintf("[%d]", a.ArrayLength)
    72  			} else {
    73  				str += "[]"
    74  			}
    75  		}
    76  		if addIndexedName && a.Name != "" {
    77  			str += " " + a.Name
    78  		}
    79  	}
    80  	str += ")"
    81  	return
    82  }