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