github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/signer/core/validation.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:42</date> 10 //</624450110570369024> 11 12 13 package core 14 15 import ( 16 "bytes" 17 "errors" 18 "fmt" 19 "math/big" 20 "regexp" 21 22 "github.com/ethereum/go-ethereum/common" 23 ) 24 25 //验证包包含对事务的验证检查 26 //-ABI数据验证 27 //-事务语义验证 28 //该包为典型的陷阱提供警告 29 30 type Validator struct { 31 db *AbiDb 32 } 33 34 func NewValidator(db *AbiDb) *Validator { 35 return &Validator{db} 36 } 37 func testSelector(selector string, data []byte) (*decodedCallData, error) { 38 if selector == "" { 39 return nil, fmt.Errorf("selector not found") 40 } 41 abiData, err := MethodSelectorToAbi(selector) 42 if err != nil { 43 return nil, err 44 } 45 info, err := parseCallData(data, string(abiData)) 46 if err != nil { 47 return nil, err 48 } 49 return info, nil 50 51 } 52 53 //validateCallData检查是否可以解析ABI数据+方法选择器(如果给定),并且似乎匹配 54 func (v *Validator) validateCallData(msgs *ValidationMessages, data []byte, methodSelector *string) { 55 if len(data) == 0 { 56 return 57 } 58 if len(data) < 4 { 59 msgs.warn("Tx contains data which is not valid ABI") 60 return 61 } 62 if arglen := len(data) - 4; arglen%32 != 0 { 63 msgs.warn(fmt.Sprintf("Not ABI-encoded data; length should be a multiple of 32 (was %d)", arglen)) 64 } 65 var ( 66 info *decodedCallData 67 err error 68 ) 69 //检查提供的一个 70 if methodSelector != nil { 71 info, err = testSelector(*methodSelector, data) 72 if err != nil { 73 msgs.warn(fmt.Sprintf("Tx contains data, but provided ABI signature could not be matched: %v", err)) 74 } else { 75 msgs.info(info.String()) 76 //成功完全匹配。如果还没有添加到数据库(忽略其中的错误) 77 v.db.AddSignature(*methodSelector, data[:4]) 78 } 79 return 80 } 81 //检查数据库 82 selector, err := v.db.LookupMethodSelector(data[:4]) 83 if err != nil { 84 msgs.warn(fmt.Sprintf("Tx contains data, but the ABI signature could not be found: %v", err)) 85 return 86 } 87 info, err = testSelector(selector, data) 88 if err != nil { 89 msgs.warn(fmt.Sprintf("Tx contains data, but provided ABI signature could not be matched: %v", err)) 90 } else { 91 msgs.info(info.String()) 92 } 93 } 94 95 //validateMantics检查事务是否“有意义”,并为几个典型场景生成警告 96 func (v *Validator) validate(msgs *ValidationMessages, txargs *SendTxArgs, methodSelector *string) error { 97 //防止意外错误地使用“输入”和“数据” 98 if txargs.Data != nil && txargs.Input != nil && !bytes.Equal(*txargs.Data, *txargs.Input) { 99 //这是一个展示台 100 return errors.New(`Ambiguous request: both "data" and "input" are set and are not identical`) 101 } 102 var ( 103 data []byte 104 ) 105 //将数据放在“data”上,不输入“input” 106 if txargs.Input != nil { 107 txargs.Data = txargs.Input 108 txargs.Input = nil 109 } 110 if txargs.Data != nil { 111 data = *txargs.Data 112 } 113 114 if txargs.To == nil { 115 //合同创建应包含足够的数据以部署合同 116 //由于javascript调用中的一些奇怪之处,一个典型的错误是忽略发送者。 117 //例如:https://github.com/ethereum/go-ethereum/issues/16106 118 if len(data) == 0 { 119 if txargs.Value.ToInt().Cmp(big.NewInt(0)) > 0 { 120 //把乙醚送入黑洞 121 return errors.New("Tx will create contract with value but empty code!") 122 } 123 //至少没有提交值 124 msgs.crit("Tx will create contract with empty code!") 125 } else if len(data) < 40 { //任意极限 126 msgs.warn(fmt.Sprintf("Tx will will create contract, but payload is suspiciously small (%d b)", len(data))) 127 } 128 //对于合同创建,methodSelector应为零 129 if methodSelector != nil { 130 msgs.warn("Tx will create contract, but method selector supplied; indicating intent to call a method.") 131 } 132 133 } else { 134 if !txargs.To.ValidChecksum() { 135 msgs.warn("Invalid checksum on to-address") 136 } 137 //正常交易 138 if bytes.Equal(txargs.To.Address().Bytes(), common.Address{}.Bytes()) { 139 //发送到0 140 msgs.crit("Tx destination is the zero address!") 141 } 142 //验证CallData 143 v.validateCallData(msgs, data, methodSelector) 144 } 145 return nil 146 } 147 148 //validateTransaction对所提供的事务执行许多检查,并返回警告列表, 149 //或错误,指示应立即拒绝该事务 150 func (v *Validator) ValidateTransaction(txArgs *SendTxArgs, methodSelector *string) (*ValidationMessages, error) { 151 msgs := &ValidationMessages{} 152 return msgs, v.validate(msgs, txArgs, methodSelector) 153 } 154 155 var Printable7BitAscii = regexp.MustCompile("^[A-Za-z0-9!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ]+$") 156 157 //如果密码太短或包含字符,则validatePasswordFormat返回错误。 158 //超出可打印7bit ASCII集的范围 159 func ValidatePasswordFormat(password string) error { 160 if len(password) < 10 { 161 return errors.New("password too short (<10 characters)") 162 } 163 if !Printable7BitAscii.MatchString(password) { 164 return errors.New("password contains invalid characters - only 7bit printable ascii allowed") 165 } 166 return nil 167 } 168