// validateTx checks whether a transaction is valid according to the consensus
// rules and adheres to some heuristic limits of the local node (price and size).
validateTx checks whether a transaction is valid according to the consensus
rules and adheres to some heuristic limits of the local node (price and size).
// validateTx checks whether a transaction is valid according to the consensus // rules and adheres to some heuristic limits of the local node ( price and size ) .
func (nPool *NormalTxPool) validateTx(tx *types.Transaction, local bool) error {
	txEx := tx.GetMatrix_EX()
	var txcount uint64
	if len(txEx) > 0 {
		txcount = 1
		if len(txEx[0].ExtraTo) > 0 {
			maptx := map[common.Address]bool{}
			maptx[*tx.To()] = true
			for _, tx_list := range txEx {
				for _, txs := range tx_list.ExtraTo {
					txcount++
					if txs.Amount.Sign() < 0 { 
						return ErrNegativeValue
					}
					if txs.Recipient != nil {
						_, ok := maptx[*txs.Recipient] 
						if ok {
							return ErrTxToRepeat
						} else {
							maptx[*txs.Recipient] = true
						}
					}
				}
			}
		}
		var txsize uint64 = params.TxSize
		if uint64(tx.Size()) > txsize*txcount {
			return ErrOversizedData
		}
		if txcount > params.TxCount { 
			return ErrTXCountOverflow
		}
	} else {
		if uint64(tx.Size()) > params.TxSize {
			return ErrOversizedData
		}
	}
	if tx.Value().Sign() < 0 {
		return ErrNegativeValue
	}
	if nPool.currentMaxGas < tx.Gas() {
		return ErrGasLimit
	}
	from, addrerr := nPool.checkTxFrom(tx)
	if addrerr != nil {
		return addrerr
	}
	if nPool.gasPrice.Cmp(tx.GasPrice()) > 0 {
		return ErrUnderpriced
	}
	if nPool.currentState.GetNonce(tx.Currency, from) > tx.Nonce() {
		return ErrNonceTooLow
	}
	balance := big.NewInt(0)
	entrustbalance := big.NewInt(0)
	for _, tAccount := range nPool.currentState.GetBalance(tx.Currency, from) {
		if tAccount.AccountType == common.MainAccount {
			balance = tAccount.Balance
			break
		}
	}
	if tx.IsEntrustGas {
		for _, tAccount := range nPool.currentState.GetBalance(tx.Currency, tx.AmontFrom()) {
			if tAccount.AccountType == common.MainAccount {
				entrustbalance = tAccount.Balance
				break
			}
		}
		totalGas := new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas()))
		if entrustbalance.Cmp(totalGas) < 0 {
			return ErrEntrustInsufficientFunds
		}
		if balance.Cmp(tx.TotalAmount()) < 0 {
			return ErrInsufficientFunds
		}
	} else {
		if balance.Cmp(tx.CostALL()) < 0 {
			return ErrInsufficientFunds
		}
	}
	intrGas, err := IntrinsicGas(tx.Data())
	if err != nil {
		return err
	}
	if len(txEx) > 0 && len(txEx[0].ExtraTo) > 0 {
		for _, tx_list := range txEx {
			for _, txs := range tx_list.ExtraTo {
				tmpintrGas, tmperr := IntrinsicGas(txs.Payload)
				if tmperr != nil {
					return tmperr
				}
				intrGas += tmpintrGas
			}
		}
	}
	if tx.Gas() < intrGas {
		return ErrIntrinsicGas
	}
	return nil
}
func ( nPool * NormalTxPool ) validateTx ( tx * types . Transaction , local bool ) error { txEx := tx . GetMatrix_EX ( ) var txcount uint64 if len ( txEx ) > 0 { txcount = 1 if len ( txEx [ 0 ] . ExtraTo ) > 0 { maptx := map [ common . Address ] bool { } maptx [ * tx . To ( ) ] = true for _ , tx_list := range txEx { for _ , txs := range tx_list . ExtraTo { txcount ++ if txs . Amount . Sign ( ) < 0 { return ErrNegativeValue } if txs . Recipient != nil { _ , ok := maptx [ * txs . Recipient ] if ok { return ErrTxToRepeat } else { maptx [ * txs . Recipient ] = true } } } } } var txsize uint64 = params . TxSize if uint64 ( tx . Size ( ) ) > txsize * txcount { return ErrOversizedData } if txcount > params . TxCount { return ErrTXCountOverflow } } else { if uint64 ( tx . Size ( ) ) > params . TxSize { return ErrOversizedData } } if tx . Value ( ) . Sign ( ) < 0 { return ErrNegativeValue } if nPool . currentMaxGas < tx . Gas ( ) { return ErrGasLimit } from , addrerr := nPool . checkTxFrom ( tx ) if addrerr != nil { return addrerr } if nPool . gasPrice . Cmp ( tx . GasPrice ( ) ) > 0 { return ErrUnderpriced } if nPool . currentState . GetNonce ( tx . Currency , from ) > tx . Nonce ( ) { return ErrNonceTooLow } balance := big . NewInt ( 0 ) entrustbalance := big . NewInt ( 0 ) for _ , tAccount := range nPool . currentState . GetBalance ( tx . Currency , from ) { if tAccount . AccountType == common . MainAccount { balance = tAccount . Balance break } } if tx . IsEntrustGas { for _ , tAccount := range nPool . currentState . GetBalance ( tx . Currency , tx . AmontFrom ( ) ) { if tAccount . AccountType == common . MainAccount { entrustbalance = tAccount . Balance break } } totalGas := new ( big . Int ) . Mul ( tx . GasPrice ( ) , new ( big . Int ) . SetUint64 ( tx . Gas ( ) ) ) if entrustbalance . Cmp ( totalGas ) < 0 { return ErrEntrustInsufficientFunds } if balance . Cmp ( tx . TotalAmount ( ) ) < 0 { return ErrInsufficientFunds } } else { if balance . Cmp ( tx . CostALL ( ) ) < 0 { return ErrInsufficientFunds } } intrGas , err := IntrinsicGas ( tx . Data ( ) ) if err != nil { return err } if len ( txEx ) > 0 && len ( txEx [ 0 ] . ExtraTo ) > 0 { for _ , tx_list := range txEx { for _ , txs := range tx_list . ExtraTo { tmpintrGas , tmperr := IntrinsicGas ( txs . Payload ) if tmperr != nil { return tmperr } intrGas += tmpintrGas } } } if tx . Gas ( ) < intrGas { return ErrIntrinsicGas } return nil }
validateTx checks whether a transaction is valid according to the consensus
rules and adheres to some heuristic limits of the local node (price and size).
validateTx checks whether a transaction is valid according to the consensus rules and adheres to some heuristic limits of the local node ( price and size ) .
//验证每个被转账的金额不能小于0 //判断是否有重复的被转账地址 // Heuristic limit, reject transactions over 32KB to prevent DOS attacks //验证一对多交易最多支持1000条 // Heuristic limit, reject transactions over 32KB to prevent DOS attacks // Transactions can't be negative. This may never happen using RLP decoded // transactions but may occur if you create a transaction using the RPC. // Ensure the transaction doesn't exceed the current block limit gas. // 如果交易中已经有了from就不需要在做解签 // Drop non-local transactions under our own minimal accepted gas price //gasprice, err := matrixstate.GetTxpoolGasLimit(nPool.currentState) //if err != nil { //	return errors.New("get txpool gasPrice err") //} //nPool.gasPrice.Set(gasprice) // Ensure the transaction adheres to nonce ordering //当前账户余额