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