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 }