github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/signer/core/validation.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2018 Go Ethereum作者 10 //此文件是Go以太坊的一部分。 11 // 12 //Go以太坊是免费软件:您可以重新发布和/或修改它 13 //根据GNU通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊的分布希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU通用公共许可证了解更多详细信息。 21 // 22 //你应该已经收到一份GNU通用公共许可证的副本 23 //一起去以太坊吧。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package core 26 27 import ( 28 "bytes" 29 "errors" 30 "fmt" 31 "math/big" 32 33 "github.com/ethereum/go-ethereum/common" 34 ) 35 36 //验证包包含对事务的验证检查 37 //-ABI数据验证 38 //-事务语义验证 39 //该包为典型的陷阱提供警告 40 41 func (vs *ValidationMessages) crit(msg string) { 42 vs.Messages = append(vs.Messages, ValidationInfo{"CRITICAL", msg}) 43 } 44 func (vs *ValidationMessages) warn(msg string) { 45 vs.Messages = append(vs.Messages, ValidationInfo{"WARNING", msg}) 46 } 47 func (vs *ValidationMessages) info(msg string) { 48 vs.Messages = append(vs.Messages, ValidationInfo{"Info", msg}) 49 } 50 51 type Validator struct { 52 db *AbiDb 53 } 54 55 func NewValidator(db *AbiDb) *Validator { 56 return &Validator{db} 57 } 58 func testSelector(selector string, data []byte) (*decodedCallData, error) { 59 if selector == "" { 60 return nil, fmt.Errorf("selector not found") 61 } 62 abiData, err := MethodSelectorToAbi(selector) 63 if err != nil { 64 return nil, err 65 } 66 info, err := parseCallData(data, string(abiData)) 67 if err != nil { 68 return nil, err 69 } 70 return info, nil 71 72 } 73 74 //validateCallData检查是否可以解析ABI数据+方法选择器(如果给定),并且似乎匹配 75 func (v *Validator) validateCallData(msgs *ValidationMessages, data []byte, methodSelector *string) { 76 if len(data) == 0 { 77 return 78 } 79 if len(data) < 4 { 80 msgs.warn("Tx contains data which is not valid ABI") 81 return 82 } 83 var ( 84 info *decodedCallData 85 err error 86 ) 87 //检查提供的一个 88 if methodSelector != nil { 89 info, err = testSelector(*methodSelector, data) 90 if err != nil { 91 msgs.warn(fmt.Sprintf("Tx contains data, but provided ABI signature could not be matched: %v", err)) 92 } else { 93 msgs.info(info.String()) 94 //成功完全匹配。如果还没有添加到数据库(忽略其中的错误) 95 v.db.AddSignature(*methodSelector, data[:4]) 96 } 97 return 98 } 99 //检查数据库 100 selector, err := v.db.LookupMethodSelector(data[:4]) 101 if err != nil { 102 msgs.warn(fmt.Sprintf("Tx contains data, but the ABI signature could not be found: %v", err)) 103 return 104 } 105 info, err = testSelector(selector, data) 106 if err != nil { 107 msgs.warn(fmt.Sprintf("Tx contains data, but provided ABI signature could not be matched: %v", err)) 108 } else { 109 msgs.info(info.String()) 110 } 111 } 112 113 //validateMantics检查事务是否“有意义”,并为几个典型场景生成警告 114 func (v *Validator) validate(msgs *ValidationMessages, txargs *SendTxArgs, methodSelector *string) error { 115 //防止意外错误地使用“输入”和“数据” 116 if txargs.Data != nil && txargs.Input != nil && !bytes.Equal(*txargs.Data, *txargs.Input) { 117 //这是一个展示台 118 return errors.New(`Ambiguous request: both "data" and "input" are set and are not identical`) 119 } 120 var ( 121 data []byte 122 ) 123 //将数据放在“data”上,不输入“input” 124 if txargs.Input != nil { 125 txargs.Data = txargs.Input 126 txargs.Input = nil 127 } 128 if txargs.Data != nil { 129 data = *txargs.Data 130 } 131 132 if txargs.To == nil { 133 //合同创建应包含足够的数据以部署合同 134 //由于javascript调用中的一些奇怪之处,一个典型的错误是忽略发送者。 135 //例如:https://github.com/ethereum/go-ethereum/issues/16106 136 if len(data) == 0 { 137 if txargs.Value.ToInt().Cmp(big.NewInt(0)) > 0 { 138 //把乙醚送入黑洞 139 return errors.New("Tx will create contract with value but empty code!") 140 } 141 //至少没有提交值 142 msgs.crit("Tx will create contract with empty code!") 143 } else if len(data) < 40 { //任意极限 144 msgs.warn(fmt.Sprintf("Tx will will create contract, but payload is suspiciously small (%d b)", len(data))) 145 } 146 //对于合同创建,methodSelector应为零 147 if methodSelector != nil { 148 msgs.warn("Tx will create contract, but method selector supplied; indicating intent to call a method.") 149 } 150 151 } else { 152 if !txargs.To.ValidChecksum() { 153 msgs.warn("Invalid checksum on to-address") 154 } 155 //正常交易 156 if bytes.Equal(txargs.To.Address().Bytes(), common.Address{}.Bytes()) { 157 //发送到0 158 msgs.crit("Tx destination is the zero address!") 159 } 160 //验证CallData 161 v.validateCallData(msgs, data, methodSelector) 162 } 163 return nil 164 } 165 166 //validateTransaction对所提供的事务执行许多检查,并返回警告列表, 167 //或错误,指示应立即拒绝该事务 168 func (v *Validator) ValidateTransaction(txArgs *SendTxArgs, methodSelector *string) (*ValidationMessages, error) { 169 msgs := &ValidationMessages{} 170 return msgs, v.validate(msgs, txArgs, methodSelector) 171 }