From 33c56ebc6757fd50e7a7ea1d594754e33d904887 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 21 Jan 2020 15:51:36 +0100 Subject: [PATCH] cmd: implement abidump (#19958) * abidump: implement abi dump command * cmd/abidump: add license --- cmd/abidump/main.go | 74 +++++++++++++++++++++++++++++++++++ signer/fourbyte/abi.go | 2 +- signer/fourbyte/validation.go | 8 ++-- 3 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 cmd/abidump/main.go diff --git a/cmd/abidump/main.go b/cmd/abidump/main.go new file mode 100644 index 000000000..35cbcbb0e --- /dev/null +++ b/cmd/abidump/main.go @@ -0,0 +1,74 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package main + +import ( + "encoding/hex" + "flag" + "fmt" + "os" + "strings" + + "github.com/ethereum/go-ethereum/signer/core" + "github.com/ethereum/go-ethereum/signer/fourbyte" +) + +func init() { + flag.Usage = func() { + fmt.Fprintln(os.Stderr, "Usage:", os.Args[0], "") + flag.PrintDefaults() + fmt.Fprintln(os.Stderr, ` +Parses the given ABI data and tries to interpret it from the fourbyte database.`) + } +} + +func parse(data []byte) { + db, err := fourbyte.New() + if err != nil { + die(err) + } + messages := core.ValidationMessages{} + db.ValidateCallData(nil, data, &messages) + for _, m := range messages.Messages { + fmt.Printf("%v: %v\n", m.Typ, m.Message) + } +} + +// Example +// ./abidump a9059cbb000000000000000000000000ea0e2dc7d65a50e77fc7e84bff3fd2a9e781ff5c0000000000000000000000000000000000000000000000015af1d78b58c40000 +func main() { + flag.Parse() + + switch { + case flag.NArg() == 1: + hexdata := flag.Arg(0) + data, err := hex.DecodeString(strings.TrimPrefix(hexdata, "0x")) + if err != nil { + die(err) + } + parse(data) + default: + fmt.Fprintln(os.Stderr, "Error: one argument needed") + flag.Usage() + os.Exit(2) + } +} + +func die(args ...interface{}) { + fmt.Fprintln(os.Stderr, args...) + os.Exit(1) +} diff --git a/signer/fourbyte/abi.go b/signer/fourbyte/abi.go index 585eae1cd..796086d41 100644 --- a/signer/fourbyte/abi.go +++ b/signer/fourbyte/abi.go @@ -137,7 +137,7 @@ func parseCallData(calldata []byte, abidata string) (*decodedCallData, error) { } values, err := method.Inputs.UnpackValues(argdata) if err != nil { - return nil, err + return nil, fmt.Errorf("signature %q matches, but arguments mismatch: %v", method.String(), err) } // Everything valid, assemble the call infos for the signer decoded := decodedCallData{signature: method.Sig(), name: method.RawName} diff --git a/signer/fourbyte/validation.go b/signer/fourbyte/validation.go index 4d042d240..fd13e0a63 100644 --- a/signer/fourbyte/validation.go +++ b/signer/fourbyte/validation.go @@ -74,13 +74,13 @@ func (db *Database) ValidateTransaction(selector *string, tx *core.SendTxArgs) ( messages.Crit("Transaction recipient is the zero address") } // Semantic fields validated, try to make heads or tails of the call data - db.validateCallData(selector, data, messages) + db.ValidateCallData(selector, data, messages) return messages, nil } -// validateCallData checks if the ABI call-data + method selector (if given) can +// ValidateCallData checks if the ABI call-data + method selector (if given) can // be parsed and seems to match. -func (db *Database) validateCallData(selector *string, data []byte, messages *core.ValidationMessages) { +func (db *Database) ValidateCallData(selector *string, data []byte, messages *core.ValidationMessages) { // If the data is empty, we have a plain value transfer, nothing more to do if len(data) == 0 { return @@ -110,7 +110,7 @@ func (db *Database) validateCallData(selector *string, data []byte, messages *co return } if info, err := verifySelector(embedded, data); err != nil { - messages.Warn(fmt.Sprintf("Transaction contains data, but provided ABI signature could not be varified: %v", err)) + messages.Warn(fmt.Sprintf("Transaction contains data, but provided ABI signature could not be verified: %v", err)) } else { messages.Info(info.String()) }