aboutsummaryrefslogtreecommitdiffstats
path: root/signer/core/validation.go
diff options
context:
space:
mode:
authorMartin Holst Swende <martin@swende.se>2018-04-16 20:04:32 +0800
committerPéter Szilágyi <peterke@gmail.com>2018-04-16 20:04:32 +0800
commitec3db0f56c779387132dcf2049ed32bf4ed34a4f (patch)
treed509c580e02053fd133b0402c0838940d4b871d2 /signer/core/validation.go
parentde2a7bb764c82dbaa80d37939c5862358174bc6e (diff)
downloadgo-tangerine-ec3db0f56c779387132dcf2049ed32bf4ed34a4f.tar
go-tangerine-ec3db0f56c779387132dcf2049ed32bf4ed34a4f.tar.gz
go-tangerine-ec3db0f56c779387132dcf2049ed32bf4ed34a4f.tar.bz2
go-tangerine-ec3db0f56c779387132dcf2049ed32bf4ed34a4f.tar.lz
go-tangerine-ec3db0f56c779387132dcf2049ed32bf4ed34a4f.tar.xz
go-tangerine-ec3db0f56c779387132dcf2049ed32bf4ed34a4f.tar.zst
go-tangerine-ec3db0f56c779387132dcf2049ed32bf4ed34a4f.zip
cmd/clef, signer: initial poc of the standalone signer (#16154)
* signer: introduce external signer command * cmd/signer, rpc: Implement new signer. Add info about remote user to Context * signer: refactored request/response, made use of urfave.cli * cmd/signer: Use common flags * cmd/signer: methods to validate calldata against abi * cmd/signer: work on abi parser * signer: add mutex around UI * cmd/signer: add json 4byte directory, remove passwords from api * cmd/signer: minor changes * cmd/signer: Use ErrRequestDenied, enable lightkdf * cmd/signer: implement tests * cmd/signer: made possible for UI to modify tx parameters * cmd/signer: refactors, removed channels in ui comms, added UI-api via stdin/out * cmd/signer: Made lowercase json-definitions, added UI-signer test functionality * cmd/signer: update documentation * cmd/signer: fix bugs, improve abi detection, abi argument display * cmd/signer: minor change in json format * cmd/signer: rework json communication * cmd/signer: implement mixcase addresses in API, fix json id bug * cmd/signer: rename fromaccount, update pythonpoc with new json encoding format * cmd/signer: make use of new abi interface * signer: documentation * signer/main: remove redundant option * signer: implement audit logging * signer: create package 'signer', minor changes * common: add 0x-prefix to mixcaseaddress in json marshalling + validation * signer, rules, storage: implement rules + ephemeral storage for signer rules * signer: implement OnApprovedTx, change signing response (API BREAKAGE) * signer: refactoring + documentation * signer/rules: implement dispatching to next handler * signer: docs * signer/rules: hide json-conversion from users, ensure context is cleaned * signer: docs * signer: implement validation rules, change signature of call_info * signer: fix log flaw with string pointer * signer: implement custom 4byte databsae that saves submitted signatures * signer/storage: implement aes-gcm-backed credential storage * accounts: implement json unmarshalling of url * signer: fix listresponse, fix gas->uint64 * node: make http/ipc start methods public * signer: add ipc capability+review concerns * accounts: correct docstring * signer: address review concerns * rpc: go fmt -s * signer: review concerns+ baptize Clef * signer,node: move Start-functions to separate file * signer: formatting
Diffstat (limited to 'signer/core/validation.go')
-rw-r--r--signer/core/validation.go163
1 files changed, 163 insertions, 0 deletions
diff --git a/signer/core/validation.go b/signer/core/validation.go
new file mode 100644
index 000000000..97bb3b685
--- /dev/null
+++ b/signer/core/validation.go
@@ -0,0 +1,163 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+
+package core
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// The validation package contains validation checks for transactions
+// - ABI-data validation
+// - Transaction semantics validation
+// The package provides warnings for typical pitfalls
+
+func (vs *ValidationMessages) crit(msg string) {
+ vs.Messages = append(vs.Messages, ValidationInfo{"CRITICAL", msg})
+}
+func (vs *ValidationMessages) warn(msg string) {
+ vs.Messages = append(vs.Messages, ValidationInfo{"WARNING", msg})
+}
+func (vs *ValidationMessages) info(msg string) {
+ vs.Messages = append(vs.Messages, ValidationInfo{"Info", msg})
+}
+
+type Validator struct {
+ db *AbiDb
+}
+
+func NewValidator(db *AbiDb) *Validator {
+ return &Validator{db}
+}
+func testSelector(selector string, data []byte) (*decodedCallData, error) {
+ if selector == "" {
+ return nil, fmt.Errorf("selector not found")
+ }
+ abiData, err := MethodSelectorToAbi(selector)
+ if err != nil {
+ return nil, err
+ }
+ info, err := parseCallData(data, string(abiData))
+ if err != nil {
+ return nil, err
+ }
+ return info, nil
+
+}
+
+// validateCallData checks if the ABI-data + methodselector (if given) can be parsed and seems to match
+func (v *Validator) validateCallData(msgs *ValidationMessages, data []byte, methodSelector *string) {
+ if len(data) == 0 {
+ return
+ }
+ if len(data) < 4 {
+ msgs.warn("Tx contains data which is not valid ABI")
+ return
+ }
+ var (
+ info *decodedCallData
+ err error
+ )
+ // Check the provided one
+ if methodSelector != nil {
+ info, err = testSelector(*methodSelector, data)
+ if err != nil {
+ msgs.warn(fmt.Sprintf("Tx contains data, but provided ABI signature could not be matched: %v", err))
+ } else {
+ msgs.info(info.String())
+ //Successfull match. add to db if not there already (ignore errors there)
+ v.db.AddSignature(*methodSelector, data[:4])
+ }
+ return
+ }
+ // Check the db
+ selector, err := v.db.LookupMethodSelector(data[:4])
+ if err != nil {
+ msgs.warn(fmt.Sprintf("Tx contains data, but the ABI signature could not be found: %v", err))
+ return
+ }
+ info, err = testSelector(selector, data)
+ if err != nil {
+ msgs.warn(fmt.Sprintf("Tx contains data, but provided ABI signature could not be matched: %v", err))
+ } else {
+ msgs.info(info.String())
+ }
+}
+
+// validateSemantics checks if the transactions 'makes sense', and generate warnings for a couple of typical scenarios
+func (v *Validator) validate(msgs *ValidationMessages, txargs *SendTxArgs, methodSelector *string) error {
+ // Prevent accidental erroneous usage of both 'input' and 'data'
+ if txargs.Data != nil && txargs.Input != nil && !bytes.Equal(*txargs.Data, *txargs.Input) {
+ // This is a showstopper
+ return errors.New(`Ambiguous request: both "data" and "input" are set and are not identical`)
+ }
+ var (
+ data []byte
+ )
+ // Place data on 'data', and nil 'input'
+ if txargs.Input != nil {
+ txargs.Data = txargs.Input
+ txargs.Input = nil
+ }
+ if txargs.Data != nil {
+ data = *txargs.Data
+ }
+
+ if txargs.To == nil {
+ //Contract creation should contain sufficient data to deploy a contract
+ // A typical error is omitting sender due to some quirk in the javascript call
+ // e.g. https://github.com/ethereum/go-ethereum/issues/16106
+ if len(data) == 0 {
+ if txargs.Value.ToInt().Cmp(big.NewInt(0)) > 0 {
+ // Sending ether into black hole
+ return errors.New(`Tx will create contract with value but empty code!`)
+ }
+ // No value submitted at least
+ msgs.crit("Tx will create contract with empty code!")
+ } else if len(data) < 40 { //Arbitrary limit
+ msgs.warn(fmt.Sprintf("Tx will will create contract, but payload is suspiciously small (%d b)", len(data)))
+ }
+ // methodSelector should be nil for contract creation
+ if methodSelector != nil {
+ msgs.warn("Tx will create contract, but method selector supplied; indicating intent to call a method.")
+ }
+
+ } else {
+ if !txargs.To.ValidChecksum() {
+ msgs.warn("Invalid checksum on to-address")
+ }
+ // Normal transaction
+ if bytes.Equal(txargs.To.Address().Bytes(), common.Address{}.Bytes()) {
+ // Sending to 0
+ msgs.crit("Tx destination is the zero address!")
+ }
+ // Validate calldata
+ v.validateCallData(msgs, data, methodSelector)
+ }
+ return nil
+}
+
+// ValidateTransaction does a number of checks on the supplied transaction, and returns either a list of warnings,
+// or an error, indicating that the transaction should be immediately rejected
+func (v *Validator) ValidateTransaction(txArgs *SendTxArgs, methodSelector *string) (*ValidationMessages, error) {
+ msgs := &ValidationMessages{}
+ return msgs, v.validate(msgs, txArgs, methodSelector)
+}