github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/cmd/burrow/commands/abi.go (about) 1 package commands 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/hyperledger/burrow/execution/evm/abi" 8 cli "github.com/jawher/mow.cli" 9 hex "github.com/tmthrgd/go-hex" 10 ) 11 12 // Abi is a command line tool for ABI encoding and decoding. Event encoding/decoding still be added 13 func Abi(output Output) func(cmd *cli.Cmd) { 14 return func(cmd *cli.Cmd) { 15 cmd.Command("list", "List the functions and events", 16 func(cmd *cli.Cmd) { 17 dirs := cmd.StringsArg("DIR", nil, "ABI file or directory") 18 19 cmd.Action = func() { 20 for _, d := range *dirs { 21 output.Printf("In %s\n", d) 22 spec, err := abi.LoadPath(d) 23 if err != nil { 24 output.Printf("could not read %s: %v", d, err) 25 } 26 for id, e := range spec.EventsByID { 27 fmt.Printf("event %s: %s\n", id, e.String()) 28 } 29 for _, f := range spec.Functions { 30 fmt.Printf("func %x: %s\n", f.FunctionID, f.String()) 31 } 32 } 33 } 34 }) 35 36 cmd.Command("encode-function-call", "ABI encode function call", 37 func(cmd *cli.Cmd) { 38 abiPath := cmd.StringOpt("abi", ".", "ABI file or directory") 39 fname := cmd.StringArg("FUNCTION", "", "Function name") 40 args := cmd.StringsArg("ARGS", nil, "Function arguments") 41 42 cmd.Spec = "--abi=<path> FUNCTION [ARGS...]" 43 44 cmd.Action = func() { 45 spec, err := abi.LoadPath(*abiPath) 46 if err != nil { 47 output.Fatalf("could not read %v: %v", *abiPath, err) 48 } 49 50 argsInInterface := make([]interface{}, len(*args)) 51 for i, a := range *args { 52 argsInInterface[i] = a 53 } 54 55 data, _, err := spec.Pack(*fname, argsInInterface...) 56 if err != nil { 57 output.Fatalf("could not encode function call %v", err) 58 } 59 60 output.Printf("%X\n", data) 61 } 62 }) 63 64 cmd.Command("decode-function-call", "ABI decode function call", 65 func(cmd *cli.Cmd) { 66 abiPath := cmd.StringOpt("abi", ".", "ABI file or directory") 67 data := cmd.StringArg("DATA", "", "Encoded function call") 68 69 cmd.Action = func() { 70 spec, err := abi.LoadPath(*abiPath) 71 if err != nil { 72 output.Fatalf("could not read %v: %v", *abiPath, err) 73 } 74 75 bs, err := hex.DecodeString(*data) 76 if err != nil { 77 output.Fatalf("could not hex decode %s: %v", data, err) 78 } 79 80 var funcid abi.FunctionID 81 copy(funcid[:], bs) 82 found := false 83 for name, fspec := range spec.Functions { 84 if fspec.FunctionID == funcid { 85 args := make([]string, len(fspec.Inputs)) 86 intf := make([]interface{}, len(args)) 87 for i := range args { 88 intf[i] = &args[i] 89 } 90 err = abi.Unpack(fspec.Inputs, bs[len(funcid):], intf...) 91 if err != nil { 92 output.Fatalf("unable to decode function %s: %v\n", name, err) 93 } 94 // prepend function argument names 95 for i, a := range args { 96 if fspec.Inputs[i].Name != "" { 97 args[i] = fspec.Inputs[i].Name + "=" + a 98 } 99 } 100 101 output.Printf(fmt.Sprintf("%s(%s)", name, strings.Join(args, ","))) 102 } 103 104 } 105 106 if !found { 107 output.Fatalf("could not find function %X\n", funcid) 108 } 109 } 110 }) 111 112 cmd.Command("decode-function-return", "ABI decode function return", 113 func(cmd *cli.Cmd) { 114 abiPath := cmd.StringOpt("abi", ".", "ABI file or directory") 115 fname := cmd.StringArg("FUNCTION", "", "Function name") 116 data := cmd.StringArg("DATA", "", "Encoded function call") 117 118 cmd.Action = func() { 119 spec, err := abi.LoadPath(*abiPath) 120 if err != nil { 121 output.Fatalf("could not read %v: %v", *abiPath, err) 122 } 123 124 bs, err := hex.DecodeString(*data) 125 if err != nil { 126 output.Fatalf("could not hex decode %s: %v", data, err) 127 } 128 129 fspec, ok := spec.Functions[*fname] 130 if !ok { 131 output.Fatalf("no such function %s\n", *fname) 132 } 133 134 args := make([]string, len(fspec.Outputs)) 135 intf := make([]interface{}, len(args)) 136 for i := range args { 137 intf[i] = &args[i] 138 } 139 err = abi.Unpack(fspec.Outputs, bs, intf...) 140 if err != nil { 141 output.Fatalf("unable to decode function %s: %v\n", *fname, err) 142 } 143 // prepend function return value names 144 for i, a := range args { 145 if fspec.Outputs[i].Name != "" { 146 args[i] = fspec.Outputs[i].Name + "=" + a 147 } 148 } 149 150 output.Printf(strings.Join(args, "\n")) 151 } 152 }) 153 } 154 }