// queueTx will queue an unknown transaction func (self *TxPool) queueTx(hash common.Hash, tx *types.Transaction) { from, _ := tx.From() // already validated if self.queue[from] == nil { self.queue[from] = make(map[common.Hash]*types.Transaction) } self.queue[from][hash] = tx }
func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, statedb *state.StateDB, block *types.Block, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) { // If we are mining this block and validating we want to set the logs back to 0 //statedb.EmptyLogs() cb := statedb.GetStateObject(coinbase.Address()) _, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, block), tx, cb) if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) { // If the account is managed, remove the invalid nonce. //from, _ := tx.From() //self.bc.TxState().RemoveNonce(from, tx.Nonce()) return nil, nil, err } // Update the state with pending changes statedb.Update() cumulative := new(big.Int).Set(usedGas.Add(usedGas, gas)) receipt := types.NewReceipt(statedb.Root().Bytes(), cumulative) logs := statedb.GetLogs(tx.Hash()) receipt.SetLogs(logs) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) glog.V(logger.Debug).Infoln(receipt) // Notify all subscribers if !transientProcess { go self.eventMux.Post(TxPostEvent{tx}) go self.eventMux.Post(logs) } return receipt, gas, err }
func (app *EthereumApplication) AppendTx(txBytes []byte) (retCode types.RetCode, result []byte, log string) { // decode and run tx tx := new(ethtypes.Transaction) rlpStream := rlp.NewStream(bytes.NewBuffer(txBytes), 0) if err := tx.DecodeRLP(rlpStream); err != nil { return types.RetCodeEncodingError, result, log } gpi := big.NewInt(1000000000) // a billion ... TODO: configurable gp := core.GasPool(*gpi) // XXX: this feels so wrong!? ret, gas, err := core.ApplyMessage(NewEnv(app.stateDB, tx), tx, &gp) if err != nil { if err == ethtypes.ErrInvalidSig || err == ethtypes.ErrInvalidPubKey { return types.RetCodeUnauthorized, result, err.Error() } else if core.IsNonceErr(err) { return types.RetCodeBadNonce, result, err.Error() } else if core.IsInvalidTxErr(err) { return types.RetCodeInsufficientFees, result, err.Error() // bad gas or value transfer } else { return types.RetCodeUnauthorized, result, err.Error() // bad pubkey recovery } } _, _ = ret, gas return types.RetCodeOK, result, log }
func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) { // If we are mining this block and validating we want to set the logs back to 0 cb := statedb.GetStateObject(coinbase.Address()) _, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, header), tx, cb) if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) { return nil, nil, err } // Update the state with pending changes statedb.Update() usedGas.Add(usedGas, gas) receipt := types.NewReceipt(statedb.Root().Bytes(), usedGas) logs := statedb.GetLogs(tx.Hash()) receipt.SetLogs(logs) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) glog.V(logger.Debug).Infoln(receipt) // Notify all subscribers if !transientProcess { go self.eventMux.Post(TxPostEvent{tx}) go self.eventMux.Post(logs) } return receipt, gas, err }
func (self *XEth) sign(tx *types.Transaction, from common.Address, didUnlock bool) (*types.Transaction, error) { hash := tx.SigHash() sig, err := self.doSign(from, hash, didUnlock) if err != nil { return tx, err } return tx.WithSignature(sig) }
func (self *XEth) sign(tx *types.Transaction, from common.Address, didUnlock bool) error { hash := tx.Hash() sig, err := self.doSign(from, hash, didUnlock) if err != nil { return err } tx.SetSignatureValues(sig) return nil }
func (pool *TxPool) addTx(tx *types.Transaction) { if _, ok := pool.txs[tx.Hash()]; !ok { pool.txs[tx.Hash()] = tx // Notify the subscribers. This event is posted in a goroutine // because it's possible that somewhere during the post "Remove transaction" // gets called which will then wait for the global tx pool lock and deadlock. go pool.eventMux.Post(TxPreEvent{tx}) } }
func (self *ImportMaster) importTx(tx *types.Transaction, blockId *bson.ObjectId) { if glog.V(logger.Info) { glog.Infoln("Importing tx", tx.Hash().Hex()) } err := self.txCollection.Insert(self.parseTx(tx, blockId)) if err != nil { clilogger.Infoln(err) } }
// 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, nil) if err != nil { panic(err) } b.txs = append(b.txs, tx) b.receipts = append(b.receipts, receipt) }
func (app *EthereumApplication) BroadcastTx(tx *ethtypes.Transaction) error { var result ctypes.TMResult buf := new(bytes.Buffer) if err := tx.EncodeRLP(buf); err != nil { return err } params := map[string]interface{}{ "tx": hex.EncodeToString(buf.Bytes()), } _, err := app.client.Call("broadcast_tx", params, &result) return err }
func (self *ImportMaster) parseTx(tx *types.Transaction, blockId *bson.ObjectId) *Transaction { hash := tx.Hash().Hex() from, err := tx.From() if err != nil { utils.Fatalf("Could not parse from address: %v", err) } var recipient string if tx.Recipient != nil { recipient = tx.Recipient.Hex() } txx := &Transaction{hash, recipient, from.Hex(), tx.Amount.String(), tx.Price.String(), tx.GasLimit.String(), tx.Payload, blockId} return txx }
// addTx will add a transaction to the pending (processable queue) list of transactions func (pool *TxPool) addTx(hash common.Hash, addr common.Address, tx *types.Transaction) { if _, ok := pool.pending[hash]; !ok { pool.pending[hash] = tx // Increment the nonce on the pending state. This can only happen if // the nonce is +1 to the previous one. pool.pendingState.SetNonce(addr, tx.Nonce()+1) // Notify the subscribers. This event is posted in a goroutine // because it's possible that somewhere during the post "Remove transaction" // gets called which will then wait for the global tx pool lock and deadlock. go pool.eventMux.Post(TxPreEvent{tx}) } }
func (self *BlockProcessor) ApplyTransaction(gp GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) { _, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, header), tx, gp) if err != nil { return nil, nil, err } // Update the state with pending changes statedb.SyncIntermediate() usedGas.Add(usedGas, gas) receipt := types.NewReceipt(statedb.Root().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.SetLogs(logs) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) glog.V(logger.Debug).Infoln(receipt) // Notify all subscribers if !transientProcess { go self.eventMux.Post(TxPostEvent{tx}) go self.eventMux.Post(logs) } return receipt, gas, err }
// 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 ) // Drop transactions under our own minimal accepted gas price if 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. if !pool.currentState().HasAccount(from) { return ErrNonExistentAccount } // Last but not least check for nonce errors if pool.currentState().GetNonce(from) > tx.Nonce() { return ErrNonce } // Check the transaction doesn't exceed the current // block limit gas. if pool.gasLimit().Cmp(tx.GasLimit) < 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.Amount.Cmp(common.Big0) < 0 { return ErrNegativeValue } // Transactor should have enough funds to cover the costs // cost == V + GP * GL total := new(big.Int).Mul(tx.Price, tx.GasLimit) total.Add(total, tx.Value()) if pool.currentState().GetBalance(from).Cmp(total) < 0 { return ErrInsufficientFunds } // Should supply enough intrinsic gas if tx.GasLimit.Cmp(IntrinsicGas(tx)) < 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.coinbase == nil { b.SetCoinbase(common.Address{}) } _, gas, err := ApplyMessage(NewEnv(b.statedb, nil, tx, b.header), tx, b.coinbase) if err != nil { panic(err) } b.statedb.SyncIntermediate() b.header.GasUsed.Add(b.header.GasUsed, gas) receipt := types.NewReceipt(b.statedb.Root().Bytes(), b.header.GasUsed) logs := b.statedb.GetLogs(tx.Hash()) receipt.SetLogs(logs) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) b.txs = append(b.txs, tx) b.receipts = append(b.receipts, receipt) }
func (self *XEth) sign(tx *types.Transaction, from common.Address, didUnlock bool) error { sig, err := self.backend.AccountManager().Sign(accounts.Account{Address: from.Bytes()}, tx.Hash().Bytes()) if err == accounts.ErrLocked { if didUnlock { return fmt.Errorf("sender account still locked after successful unlock") } if !self.frontend.UnlockAccount(from.Bytes()) { return fmt.Errorf("could not unlock sender account") } // retry signing, the account should now be unlocked. return self.sign(tx, from, true) } else if err != nil { return err } tx.SetSignatureValues(sig) return nil }
func (gui *Gui) insertTransaction(window string, tx *types.Transaction) { var inout string from, _ := tx.From() if gui.eth.AccountManager().HasAccount(common.Hex2Bytes(from.Hex())) { inout = "send" } else { inout = "recv" } ptx := xeth.NewTx(tx) ptx.Sender = from.Hex() if to := tx.To(); to != nil { ptx.Address = to.Hex() } if window == "post" { //gui.getObjectByName("transactionView").Call("addTx", ptx, inout) } else { gui.getObjectByName("pendingTxView").Call("addTx", ptx, inout) } }
// 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 }
func putTx(db common.Database, tx *types.Transaction, block *types.Block, i uint64) { rlpEnc, err := rlp.EncodeToBytes(tx) if err != nil { glog.V(logger.Debug).Infoln("Failed encoding tx", err) return } db.Put(tx.Hash().Bytes(), rlpEnc) var txExtra struct { BlockHash common.Hash BlockIndex uint64 Index uint64 } txExtra.BlockHash = block.Hash() txExtra.BlockIndex = block.NumberU64() txExtra.Index = i rlpMeta, err := rlp.EncodeToBytes(txExtra) if err != nil { glog.V(logger.Debug).Infoln("Failed encoding tx meta data", err) return } db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) }
// keep accounts synced up func (self *Ethereum) syncAccounts(tx *types.Transaction) { from, err := tx.From() if err != nil { return } if self.accountManager.HasAccount(from.Bytes()) { if self.chainManager.TxState().GetNonce(from) < tx.Nonce() { self.chainManager.TxState().SetNonce(from, tx.Nonce()) } } }
func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error { // Validate sender var ( from common.Address err error ) if from, err = tx.From(); err != nil { return ErrInvalidSender } // Validate curve param v, _, _ := tx.Curve() if v > 28 || v < 27 { return fmt.Errorf("tx.v != (28 || 27) => %v", v) } if !pool.currentState().HasAccount(from) { return ErrNonExistentAccount } if pool.gasLimit().Cmp(tx.GasLimit) < 0 { return ErrGasLimit } total := new(big.Int).Mul(tx.Price, tx.GasLimit) total.Add(total, tx.Value()) if pool.currentState().GetBalance(from).Cmp(total) < 0 { return ErrInsufficientFunds } if tx.GasLimit.Cmp(IntrinsicGas(tx)) < 0 { return ErrIntrinsicGas } if pool.currentState().GetNonce(from) > tx.Nonce() { return ErrNonce } return nil }
func (self *TxPool) add(tx *types.Transaction) error { hash := tx.Hash() /* XXX I'm unsure about this. This is extremely dangerous and may result in total black listing of certain transactions if self.invalidHashes.Has(hash) { return fmt.Errorf("Invalid transaction (%x)", hash[:4]) } */ if self.txs[hash] != nil { return fmt.Errorf("Known transaction (%x)", hash[:4]) } err := self.ValidateTransaction(tx) if err != nil { return err } self.queueTx(tx) 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]) if glog.V(logger.Debug) { glog.Infof("(t) %x => %s (%v) %x\n", from, toname, tx.Value, tx.Hash()) } return nil }
// ApplyTransaction attempts 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(config *ChainConfig, bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config) (*types.Receipt, vm.Logs, *big.Int, error) { _, gas, err := ApplyMessage(NewEnv(statedb, config, bc, tx, header, cfg), 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 }
func verifyTxFields(txTest TransactionTest, decodedTx *types.Transaction) (err error) { defer func() { if recovered := recover(); recovered != nil { buf := make([]byte, 64<<10) buf = buf[:runtime.Stack(buf, false)] err = fmt.Errorf("%v\n%s", recovered, buf) } }() decodedSender, err := decodedTx.From() if err != nil { return err } expectedSender := mustConvertAddress(txTest.Sender) if expectedSender != decodedSender { return fmt.Errorf("Sender mismatch: %v %v", expectedSender, decodedSender) } expectedData := mustConvertBytes(txTest.Transaction.Data) if !bytes.Equal(expectedData, decodedTx.Data()) { return fmt.Errorf("Tx input data mismatch: %#v %#v", expectedData, decodedTx.Data()) } expectedGasLimit := mustConvertBigInt(txTest.Transaction.GasLimit, 16) if expectedGasLimit.Cmp(decodedTx.Gas()) != 0 { return fmt.Errorf("GasLimit mismatch: %v %v", expectedGasLimit, decodedTx.Gas()) } expectedGasPrice := mustConvertBigInt(txTest.Transaction.GasPrice, 16) if expectedGasPrice.Cmp(decodedTx.GasPrice()) != 0 { return fmt.Errorf("GasPrice mismatch: %v %v", expectedGasPrice, decodedTx.GasPrice()) } expectedNonce := mustConvertUint(txTest.Transaction.Nonce, 16) if expectedNonce != decodedTx.Nonce() { return fmt.Errorf("Nonce mismatch: %v %v", expectedNonce, decodedTx.Nonce()) } v, r, s := decodedTx.SignatureValues() expectedR := mustConvertBigInt(txTest.Transaction.R, 16) if r.Cmp(expectedR) != 0 { return fmt.Errorf("R mismatch: %v %v", expectedR, r) } expectedS := mustConvertBigInt(txTest.Transaction.S, 16) if s.Cmp(expectedS) != 0 { return fmt.Errorf("S mismatch: %v %v", expectedS, s) } expectedV := mustConvertUint(txTest.Transaction.V, 16) if uint64(v) != expectedV { return fmt.Errorf("V mismatch: %v %v", expectedV, v) } expectedTo := mustConvertAddress(txTest.Transaction.To) if decodedTx.To() == nil { if expectedTo != common.BytesToAddress([]byte{}) { // "empty" or "zero" address return fmt.Errorf("To mismatch when recipient is nil (contract creation): %v", expectedTo) } } else { if expectedTo != *decodedTx.To() { return fmt.Errorf("To mismatch: %v %v", expectedTo, *decodedTx.To()) } } expectedValue := mustConvertBigInt(txTest.Transaction.Value, 16) if expectedValue.Cmp(decodedTx.Value()) != 0 { return fmt.Errorf("Value mismatch: %v %v", expectedValue, decodedTx.Value()) } return nil }
func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) { // this minimalistic recoding is enough (works for natspec.js) var jsontx = fmt.Sprintf(`{"params":[{"to":"%s","data": "%s"}]}`, toStr, codeStr) if !self.ConfirmTransaction(jsontx) { err := fmt.Errorf("Transaction not confirmed") return "", err } var ( from = common.HexToAddress(fromStr) to = common.HexToAddress(toStr) value = common.Big(valueStr) gas *big.Int price *big.Int data []byte contractCreation bool ) if len(gasStr) == 0 { gas = DefaultGas() } else { gas = common.Big(gasStr) } if len(gasPriceStr) == 0 { price = self.DefaultGasPrice() } else { price = common.Big(gasPriceStr) } data = common.FromHex(codeStr) if len(toStr) == 0 { contractCreation = true } // 2015-05-18 Is this still needed? // TODO if no_private_key then //if _, exists := p.register[args.From]; exists { // p.register[args.From] = append(p.register[args.From], args) //} else { /* account := accounts.Get(common.FromHex(args.From)) if account != nil { if account.Unlocked() { if !unlockAccount(account) { return } } result, _ := account.Transact(common.FromHex(args.To), common.FromHex(args.Value), common.FromHex(args.Gas), common.FromHex(args.GasPrice), common.FromHex(args.Data)) if len(result) > 0 { *reply = common.ToHex(result) } } else if _, exists := p.register[args.From]; exists { p.register[ags.From] = append(p.register[args.From], args) } */ // TODO: align default values to have the same type, e.g. not depend on // common.Value conversions later on var nonce uint64 if len(nonceStr) != 0 { nonce = common.Big(nonceStr).Uint64() } else { state := self.backend.TxPool().State() nonce = state.GetNonce(from) } var tx *types.Transaction if contractCreation { tx = types.NewContractCreation(nonce, value, gas, price, data) } else { tx = types.NewTransaction(nonce, to, value, gas, price, data) } signed, err := self.sign(tx, from, false) if err != nil { return "", err } if err = self.backend.TxPool().Add(signed); err != nil { return "", err } if contractCreation { addr := crypto.CreateAddress(from, 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 signed.Hash().Hex(), nil }
func (p *peer) sendTransaction(tx *types.Transaction) error { p.txHashes.Add(tx.Hash()) return p2p.Send(p.rw, TxMsg, []*types.Transaction{tx}) }
// Transact forms a transaction from the given arguments and submits it to the // transactio pool for execution. func (be *registryAPIBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) { if len(toStr) > 0 && toStr != "0x" && !common.IsHexAddress(toStr) { return "", errors.New("invalid address") } var ( from = common.HexToAddress(fromStr) to = common.HexToAddress(toStr) value = common.Big(valueStr) gas *big.Int price *big.Int data []byte contractCreation bool ) if len(gasStr) == 0 { gas = big.NewInt(90000) } else { gas = common.Big(gasStr) } if len(gasPriceStr) == 0 { price = big.NewInt(10000000000000) } else { price = common.Big(gasPriceStr) } data = common.FromHex(codeStr) if len(toStr) == 0 { contractCreation = true } nonce := be.txPool.State().GetNonce(from) if len(nonceStr) != 0 { nonce = common.Big(nonceStr).Uint64() } var tx *types.Transaction if contractCreation { tx = types.NewContractCreation(nonce, value, gas, price, data) } else { tx = types.NewTransaction(nonce, to, value, gas, price, data) } acc := accounts.Account{from} signature, err := be.am.Sign(acc, tx.SigHash().Bytes()) if err != nil { return "", err } signedTx, err := tx.WithSignature(signature) if err != nil { return "", err } be.txPool.SetLocal(signedTx) if err := be.txPool.Add(signedTx); err != nil { return "", nil } if contractCreation { addr := crypto.CreateAddress(from, nonce) glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signedTx.Hash().Hex(), addr.Hex()) } else { glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signedTx.Hash().Hex(), tx.To().Hex()) } return signedTx.Hash().Hex(), nil }
// validateTx checks whether a transaction is valid according // to the consensus rules. func (pool *TxPool) validateTx(tx *types.Transaction) 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 } currentState, err := pool.currentState() if err != nil { return err } from, err := tx.From() if err != nil { return ErrInvalidSender } // Make sure the account exist. Non existent accounts // haven't got funds and well therefor never pass. 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 } intrGas := IntrinsicGas(tx.Data(), MessageCreatesContract(tx), pool.homestead) if tx.Gas().Cmp(intrGas) < 0 { return ErrIntrinsicGas } return 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()) }
func newTx(t *types.Transaction) *tx { from, _ := t.From() var to string if t := t.To(); t != nil { to = t.Hex() } return &tx{ tx: t, To: to, From: from.Hex(), Value: t.Value().String(), Nonce: strconv.Itoa(int(t.Nonce())), Data: "0x" + common.Bytes2Hex(t.Data()), GasLimit: t.Gas().String(), GasPrice: t.GasPrice().String(), } }