github.com/felberj/go-ethereum@v1.8.23/signer/core/validation.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package core 18 19 import ( 20 "bytes" 21 "errors" 22 "fmt" 23 "math/big" 24 "regexp" 25 26 "github.com/ethereum/go-ethereum/common" 27 ) 28 29 // The validation package contains validation checks for transactions 30 // - ABI-data validation 31 // - Transaction semantics validation 32 // The package provides warnings for typical pitfalls 33 34 type Validator struct { 35 db *AbiDb 36 } 37 38 func NewValidator(db *AbiDb) *Validator { 39 return &Validator{db} 40 } 41 func testSelector(selector string, data []byte) (*decodedCallData, error) { 42 if selector == "" { 43 return nil, fmt.Errorf("selector not found") 44 } 45 abiData, err := MethodSelectorToAbi(selector) 46 if err != nil { 47 return nil, err 48 } 49 info, err := parseCallData(data, string(abiData)) 50 if err != nil { 51 return nil, err 52 } 53 return info, nil 54 55 } 56 57 // validateCallData checks if the ABI-data + methodselector (if given) can be parsed and seems to match 58 func (v *Validator) validateCallData(msgs *ValidationMessages, data []byte, methodSelector *string) { 59 if len(data) == 0 { 60 return 61 } 62 if len(data) < 4 { 63 msgs.warn("Tx contains data which is not valid ABI") 64 return 65 } 66 if arglen := len(data) - 4; arglen%32 != 0 { 67 msgs.warn(fmt.Sprintf("Not ABI-encoded data; length should be a multiple of 32 (was %d)", arglen)) 68 } 69 var ( 70 info *decodedCallData 71 err error 72 ) 73 // Check the provided one 74 if methodSelector != nil { 75 info, err = testSelector(*methodSelector, data) 76 if err != nil { 77 msgs.warn(fmt.Sprintf("Tx contains data, but provided ABI signature could not be matched: %v", err)) 78 } else { 79 msgs.info(info.String()) 80 //Successfull match. add to db if not there already (ignore errors there) 81 v.db.AddSignature(*methodSelector, data[:4]) 82 } 83 return 84 } 85 // Check the db 86 selector, err := v.db.LookupMethodSelector(data[:4]) 87 if err != nil { 88 msgs.warn(fmt.Sprintf("Tx contains data, but the ABI signature could not be found: %v", err)) 89 return 90 } 91 info, err = testSelector(selector, data) 92 if err != nil { 93 msgs.warn(fmt.Sprintf("Tx contains data, but provided ABI signature could not be matched: %v", err)) 94 } else { 95 msgs.info(info.String()) 96 } 97 } 98 99 // validateSemantics checks if the transactions 'makes sense', and generate warnings for a couple of typical scenarios 100 func (v *Validator) validate(msgs *ValidationMessages, txargs *SendTxArgs, methodSelector *string) error { 101 // Prevent accidental erroneous usage of both 'input' and 'data' 102 if txargs.Data != nil && txargs.Input != nil && !bytes.Equal(*txargs.Data, *txargs.Input) { 103 // This is a showstopper 104 return errors.New(`Ambiguous request: both "data" and "input" are set and are not identical`) 105 } 106 var ( 107 data []byte 108 ) 109 // Place data on 'data', and nil 'input' 110 if txargs.Input != nil { 111 txargs.Data = txargs.Input 112 txargs.Input = nil 113 } 114 if txargs.Data != nil { 115 data = *txargs.Data 116 } 117 118 if txargs.To == nil { 119 //Contract creation should contain sufficient data to deploy a contract 120 // A typical error is omitting sender due to some quirk in the javascript call 121 // e.g. https://github.com/ethereum/go-ethereum/issues/16106 122 if len(data) == 0 { 123 if txargs.Value.ToInt().Cmp(big.NewInt(0)) > 0 { 124 // Sending ether into black hole 125 return errors.New("Tx will create contract with value but empty code!") 126 } 127 // No value submitted at least 128 msgs.crit("Tx will create contract with empty code!") 129 } else if len(data) < 40 { //Arbitrary limit 130 msgs.warn(fmt.Sprintf("Tx will will create contract, but payload is suspiciously small (%d b)", len(data))) 131 } 132 // methodSelector should be nil for contract creation 133 if methodSelector != nil { 134 msgs.warn("Tx will create contract, but method selector supplied; indicating intent to call a method.") 135 } 136 137 } else { 138 if !txargs.To.ValidChecksum() { 139 msgs.warn("Invalid checksum on to-address") 140 } 141 // Normal transaction 142 if bytes.Equal(txargs.To.Address().Bytes(), common.Address{}.Bytes()) { 143 // Sending to 0 144 msgs.crit("Tx destination is the zero address!") 145 } 146 // Validate calldata 147 v.validateCallData(msgs, data, methodSelector) 148 } 149 return nil 150 } 151 152 // ValidateTransaction does a number of checks on the supplied transaction, and returns either a list of warnings, 153 // or an error, indicating that the transaction should be immediately rejected 154 func (v *Validator) ValidateTransaction(txArgs *SendTxArgs, methodSelector *string) (*ValidationMessages, error) { 155 msgs := &ValidationMessages{} 156 return msgs, v.validate(msgs, txArgs, methodSelector) 157 } 158 159 var Printable7BitAscii = regexp.MustCompile("^[A-Za-z0-9!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ]+$") 160 161 // ValidatePasswordFormat returns an error if the password is too short, or consists of characters 162 // outside the range of the printable 7bit ascii set 163 func ValidatePasswordFormat(password string) error { 164 if len(password) < 10 { 165 return errors.New("password too short (<10 characters)") 166 } 167 if !Printable7BitAscii.MatchString(password) { 168 return errors.New("password contains invalid characters - only 7bit printable ascii allowed") 169 } 170 return nil 171 }