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