// validate and queue transactions. func (self *TxPool) add(tx *types.Transaction) error { hash := tx.Hash() if self.pending[hash] != nil { return fmt.Errorf("Known transaction (%x)", hash[:4]) } err := self.validateTx(tx) if err != nil { return err } self.queueTx(hash, tx) if glog.V(logger.Debug) { var toname string if to := tx.To(); to != nil { toname = common.Bytes2Hex(to[:4]) } else { toname = "[NEW_CONTRACT]" } // we can ignore the error here because From is // verified in ValidateTransaction. f, _ := tx.From() from := common.Bytes2Hex(f[:4]) glog.Infof("(t) %x => %s (%v) %x\n", from, toname, tx.Value, hash) } return nil }
// validateTx checks whether a transaction is valid according // to the consensus rules. func (pool *TxPool) validateTx(tx *types.Transaction) error { // Validate sender var ( from common.Address err error ) local := pool.localTx.contains(tx.Hash()) // Drop transactions under our own minimal accepted gas price if !local && pool.minGasPrice.Cmp(tx.GasPrice()) > 0 { return ErrCheap } // Validate the transaction sender and it's sig. Throw // if the from fields is invalid. if from, err = tx.From(); err != nil { return ErrInvalidSender } // Make sure the account exist. Non existent accounts // haven't got funds and well therefor never pass. currentState, err := pool.currentState() if err != nil { return err } if !currentState.HasAccount(from) { return ErrNonExistentAccount } // Last but not least check for nonce errors if currentState.GetNonce(from) > tx.Nonce() { return ErrNonce } // Check the transaction doesn't exceed the current // block limit gas. if pool.gasLimit().Cmp(tx.Gas()) < 0 { return ErrGasLimit } // Transactions can't be negative. This may never happen // using RLP decoded transactions but may occur if you create // a transaction using the RPC for example. if tx.Value().Cmp(common.Big0) < 0 { return ErrNegativeValue } // Transactor should have enough funds to cover the costs // cost == V + GP * GL if currentState.GetBalance(from).Cmp(tx.Cost()) < 0 { return ErrInsufficientFunds } // Should supply enough intrinsic gas if tx.Gas().Cmp(IntrinsicGas(tx.Data())) < 0 { return ErrIntrinsicGas } return nil }
// AddTx adds a transaction to the generated block. If no coinbase has // been set, the block's coinbase is set to the zero address. // // AddTx panics if the transaction cannot be executed. In addition to // the protocol-imposed limitations (gas limit, etc.), there are some // further limitations on the content of transactions that can be // added. Notably, contract code relying on the BLOCKHASH instruction // will panic during execution. func (b *BlockGen) AddTx(tx *types.Transaction) { if b.gasPool == nil { b.SetCoinbase(common.Address{}) } b.statedb.StartRecord(tx.Hash(), common.Hash{}, len(b.txs)) receipt, _, _, err := ApplyTransaction(nil, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed) if err != nil { panic(err) } b.txs = append(b.txs, tx) b.receipts = append(b.receipts, receipt) }
// newRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation func newRPCPendingTransaction(tx *types.Transaction) *RPCTransaction { from, _ := tx.From() return &RPCTransaction{ From: from, Gas: rpc.NewHexNumber(tx.Gas()), GasPrice: rpc.NewHexNumber(tx.GasPrice()), Hash: tx.Hash(), Input: fmt.Sprintf("0x%x", tx.Data()), Nonce: rpc.NewHexNumber(tx.Nonce()), To: tx.To(), Value: rpc.NewHexNumber(tx.Value()), } }
func newTx(t *types.Transaction) *Tx { from, _ := t.From() return &Tx{ tx: t, To: t.To(), From: from, Value: rpc.NewHexNumber(t.Value()), Nonce: rpc.NewHexNumber(t.Nonce()), Data: "0x" + common.Bytes2Hex(t.Data()), GasLimit: rpc.NewHexNumber(t.Gas()), GasPrice: rpc.NewHexNumber(t.GasPrice()), Hash: t.Hash(), } }
// ApplyTransaction attemps to apply a transaction to the given state database // and uses the input parameters for its environment. // // ApplyTransactions returns the generated receipts and vm logs during the // execution of the state transition phase. func ApplyTransaction(bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int) (*types.Receipt, vm.Logs, *big.Int, error) { _, gas, err := ApplyMessage(NewEnv(statedb, bc, tx, header), tx, gp) if err != nil { return nil, nil, nil, err } // Update the state with pending changes usedGas.Add(usedGas, gas) receipt := types.NewReceipt(statedb.IntermediateRoot().Bytes(), usedGas) receipt.TxHash = tx.Hash() receipt.GasUsed = new(big.Int).Set(gas) if MessageCreatesContract(tx) { from, _ := tx.From() receipt.ContractAddress = crypto.CreateAddress(from, tx.Nonce()) } logs := statedb.GetLogs(tx.Hash()) receipt.Logs = logs receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) glog.V(logger.Debug).Infoln(receipt) return receipt, logs, gas, err }
// SendRawTransaction will add the signed transaction to the transaction pool. // The sender is responsible for signing the transaction and using the correct nonce. func (s *PublicTransactionPoolAPI) SendRawTransaction(encodedTx string) (string, error) { tx := new(types.Transaction) if err := rlp.DecodeBytes(common.FromHex(encodedTx), tx); err != nil { return "", err } s.txPool.SetLocal(tx) if err := s.txPool.Add(tx); err != nil { return "", err } if tx.To() == nil { from, err := tx.From() if err != nil { return "", err } addr := crypto.CreateAddress(from, tx.Nonce()) glog.V(logger.Info).Infof("Tx(%x) created: %x\n", tx.Hash(), addr) } else { glog.V(logger.Info).Infof("Tx(%x) to: %x\n", tx.Hash(), tx.To()) } return tx.Hash().Hex(), nil }
// SetLocal marks a transaction as local, skipping gas price // check against local miner minimum in the future func (pool *TxPool) SetLocal(tx *types.Transaction) { pool.mu.Lock() defer pool.mu.Unlock() pool.localTx.add(tx.Hash()) }