forked from cerc-io/plugeth
Merge pull request #1260 from obscuren/tx-drop-low-tx
core: drop low gas tx
This commit is contained in:
commit
cc0b451119
@ -1,6 +1,7 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -95,3 +96,13 @@ func (a *Address) Set(other Address) {
|
|||||||
a[i] = v
|
a[i] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PP Pretty Prints a byte slice in the following format:
|
||||||
|
// hex(value[:4])...(hex[len(value)-4:])
|
||||||
|
func PP(value []byte) string {
|
||||||
|
if len(value) <= 8 {
|
||||||
|
return Bytes2Hex(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%x...%x", value[:4], value[len(value)-4])
|
||||||
|
}
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@ -235,15 +234,8 @@ func (bc *ChainManager) setLastState() {
|
|||||||
if block != nil {
|
if block != nil {
|
||||||
bc.currentBlock = block
|
bc.currentBlock = block
|
||||||
bc.lastBlockHash = block.Hash()
|
bc.lastBlockHash = block.Hash()
|
||||||
} else { // TODO CLEAN THIS UP TMP CODE
|
} else {
|
||||||
block = bc.GetBlockByNumber(400000)
|
glog.Fatalf("Fatal. LastBlock not found. Please run removedb and resync")
|
||||||
if block == nil {
|
|
||||||
fmt.Println("Fatal. LastBlock not found. Report this issue")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
bc.currentBlock = block
|
|
||||||
bc.lastBlockHash = block.Hash()
|
|
||||||
bc.insert(block)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bc.Reset()
|
bc.Reset()
|
||||||
|
@ -19,6 +19,7 @@ var (
|
|||||||
// Transaction Pool Errors
|
// Transaction Pool Errors
|
||||||
ErrInvalidSender = errors.New("Invalid sender")
|
ErrInvalidSender = errors.New("Invalid sender")
|
||||||
ErrNonce = errors.New("Nonce too low")
|
ErrNonce = errors.New("Nonce too low")
|
||||||
|
ErrCheap = errors.New("Gas price too low for acceptance")
|
||||||
ErrBalance = errors.New("Insufficient balance")
|
ErrBalance = errors.New("Insufficient balance")
|
||||||
ErrNonExistentAccount = errors.New("Account does not exist or account balance too low")
|
ErrNonExistentAccount = errors.New("Account does not exist or account balance too low")
|
||||||
ErrInsufficientFunds = errors.New("Insufficient funds for gas * price + value")
|
ErrInsufficientFunds = errors.New("Insufficient funds for gas * price + value")
|
||||||
@ -27,6 +28,10 @@ var (
|
|||||||
ErrNegativeValue = errors.New("Negative value")
|
ErrNegativeValue = errors.New("Negative value")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
maxQueued = 200 // max limit of queued txs per address
|
||||||
|
)
|
||||||
|
|
||||||
type stateFn func() *state.StateDB
|
type stateFn func() *state.StateDB
|
||||||
|
|
||||||
// TxPool contains all currently known transactions. Transactions
|
// TxPool contains all currently known transactions. Transactions
|
||||||
@ -41,6 +46,7 @@ type TxPool struct {
|
|||||||
currentState stateFn // The state function which will allow us to do some pre checkes
|
currentState stateFn // The state function which will allow us to do some pre checkes
|
||||||
pendingState *state.ManagedState
|
pendingState *state.ManagedState
|
||||||
gasLimit func() *big.Int // The current gas limit function callback
|
gasLimit func() *big.Int // The current gas limit function callback
|
||||||
|
minGasPrice *big.Int
|
||||||
eventMux *event.TypeMux
|
eventMux *event.TypeMux
|
||||||
events event.Subscription
|
events event.Subscription
|
||||||
|
|
||||||
@ -57,8 +63,9 @@ func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func(
|
|||||||
eventMux: eventMux,
|
eventMux: eventMux,
|
||||||
currentState: currentStateFn,
|
currentState: currentStateFn,
|
||||||
gasLimit: gasLimitFn,
|
gasLimit: gasLimitFn,
|
||||||
|
minGasPrice: new(big.Int),
|
||||||
pendingState: state.ManageState(currentStateFn()),
|
pendingState: state.ManageState(currentStateFn()),
|
||||||
events: eventMux.Subscribe(ChainEvent{}),
|
events: eventMux.Subscribe(ChainEvent{}, GasPriceChanged{}),
|
||||||
}
|
}
|
||||||
go pool.eventLoop()
|
go pool.eventLoop()
|
||||||
|
|
||||||
@ -69,10 +76,15 @@ func (pool *TxPool) eventLoop() {
|
|||||||
// Track chain events. When a chain events occurs (new chain canon block)
|
// Track chain events. When a chain events occurs (new chain canon block)
|
||||||
// we need to know the new state. The new state will help us determine
|
// we need to know the new state. The new state will help us determine
|
||||||
// the nonces in the managed state
|
// the nonces in the managed state
|
||||||
for _ = range pool.events.Chan() {
|
for ev := range pool.events.Chan() {
|
||||||
pool.mu.Lock()
|
pool.mu.Lock()
|
||||||
|
|
||||||
|
switch ev := ev.(type) {
|
||||||
|
case ChainEvent:
|
||||||
pool.resetState()
|
pool.resetState()
|
||||||
|
case GasPriceChanged:
|
||||||
|
pool.minGasPrice = ev.Price
|
||||||
|
}
|
||||||
|
|
||||||
pool.mu.Unlock()
|
pool.mu.Unlock()
|
||||||
}
|
}
|
||||||
@ -124,6 +136,11 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
|
|||||||
err error
|
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
|
// Validate the transaction sender and it's sig. Throw
|
||||||
// if the from fields is invalid.
|
// if the from fields is invalid.
|
||||||
if from, err = tx.From(); err != nil {
|
if from, err = tx.From(); err != nil {
|
||||||
@ -335,7 +352,16 @@ func (pool *TxPool) checkQueue() {
|
|||||||
// Find the next consecutive nonce range starting at the
|
// Find the next consecutive nonce range starting at the
|
||||||
// current account nonce.
|
// current account nonce.
|
||||||
sort.Sort(addq)
|
sort.Sort(addq)
|
||||||
for _, e := range addq {
|
for i, e := range addq {
|
||||||
|
// start deleting the transactions from the queue if they exceed the limit
|
||||||
|
if i > maxQueued {
|
||||||
|
if glog.V(logger.Debug) {
|
||||||
|
glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(e.hash[:]))
|
||||||
|
}
|
||||||
|
delete(pool.queue[address], e.hash)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if e.AccountNonce > guessedNonce {
|
if e.AccountNonce > guessedNonce {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -310,6 +310,7 @@ func New(config *Config) (*Ethereum, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
eth.txPool = core.NewTxPool(eth.EventMux(), eth.chainManager.State, eth.chainManager.GasLimit)
|
eth.txPool = core.NewTxPool(eth.EventMux(), eth.chainManager.State, eth.chainManager.GasLimit)
|
||||||
|
|
||||||
eth.blockProcessor = core.NewBlockProcessor(stateDb, extraDb, eth.pow, eth.chainManager, eth.EventMux())
|
eth.blockProcessor = core.NewBlockProcessor(stateDb, extraDb, eth.pow, eth.chainManager, eth.EventMux())
|
||||||
eth.chainManager.SetProcessor(eth.blockProcessor)
|
eth.chainManager.SetProcessor(eth.blockProcessor)
|
||||||
eth.protocolManager = NewProtocolManager(config.ProtocolVersion, config.NetworkId, eth.eventMux, eth.txPool, eth.chainManager)
|
eth.protocolManager = NewProtocolManager(config.ProtocolVersion, config.NetworkId, eth.eventMux, eth.txPool, eth.chainManager)
|
||||||
|
@ -77,7 +77,7 @@ func (m *Miner) SetGasPrice(price *big.Int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
m.worker.gasPrice = price
|
m.worker.setGasPrice(price)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Miner) Start(coinbase common.Address, threads int) {
|
func (self *Miner) Start(coinbase common.Address, threads int) {
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -374,6 +375,8 @@ func (self *worker) commitNewWork() {
|
|||||||
self.currentMu.Lock()
|
self.currentMu.Lock()
|
||||||
defer self.currentMu.Unlock()
|
defer self.currentMu.Unlock()
|
||||||
|
|
||||||
|
tstart := time.Now()
|
||||||
|
|
||||||
previous := self.current
|
previous := self.current
|
||||||
self.makeCurrent()
|
self.makeCurrent()
|
||||||
current := self.current
|
current := self.current
|
||||||
@ -409,7 +412,7 @@ func (self *worker) commitNewWork() {
|
|||||||
|
|
||||||
// We only care about logging if we're actually mining
|
// We only care about logging if we're actually mining
|
||||||
if atomic.LoadInt32(&self.mining) == 1 {
|
if atomic.LoadInt32(&self.mining) == 1 {
|
||||||
glog.V(logger.Info).Infof("commit new work on block %v with %d txs & %d uncles\n", current.block.Number(), current.tcount, len(uncles))
|
glog.V(logger.Info).Infof("commit new work on block %v with %d txs & %d uncles. Took %v\n", current.block.Number(), current.tcount, len(uncles), time.Since(tstart))
|
||||||
self.logLocalMinedBlocks(previous)
|
self.logLocalMinedBlocks(previous)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,7 +440,6 @@ func (self *worker) commitUncle(uncle *types.Header) error {
|
|||||||
// Error not unique
|
// Error not unique
|
||||||
return core.UncleError("Uncle not unique")
|
return core.UncleError("Uncle not unique")
|
||||||
}
|
}
|
||||||
self.current.uncles.Add(uncle.Hash())
|
|
||||||
|
|
||||||
if !self.current.ancestors.Has(uncle.ParentHash) {
|
if !self.current.ancestors.Has(uncle.ParentHash) {
|
||||||
return core.UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4]))
|
return core.UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4]))
|
||||||
@ -446,6 +448,7 @@ func (self *worker) commitUncle(uncle *types.Header) error {
|
|||||||
if self.current.family.Has(uncle.Hash()) {
|
if self.current.family.Has(uncle.Hash()) {
|
||||||
return core.UncleError(fmt.Sprintf("Uncle already in family (%x)", uncle.Hash()))
|
return core.UncleError(fmt.Sprintf("Uncle already in family (%x)", uncle.Hash()))
|
||||||
}
|
}
|
||||||
|
self.current.uncles.Add(uncle.Hash())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -259,7 +259,14 @@ func (self *ethApi) SendTransaction(req *shared.Request) (interface{}, error) {
|
|||||||
nonce = args.Nonce.String()
|
nonce = args.Nonce.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := self.xeth.Transact(args.From, args.To, nonce, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
|
var gas, price string
|
||||||
|
if args.Gas != nil {
|
||||||
|
gas = args.Gas.String()
|
||||||
|
}
|
||||||
|
if args.GasPrice != nil {
|
||||||
|
price = args.GasPrice.String()
|
||||||
|
}
|
||||||
|
v, err := self.xeth.Transact(args.From, args.To, nonce, args.Value.String(), gas, price, args.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -333,9 +333,7 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
|
|||||||
args.Value = num
|
args.Value = num
|
||||||
|
|
||||||
num = nil
|
num = nil
|
||||||
if ext.Gas == nil {
|
if ext.Gas != nil {
|
||||||
num = big.NewInt(0)
|
|
||||||
} else {
|
|
||||||
if num, err = numString(ext.Gas); err != nil {
|
if num, err = numString(ext.Gas); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -343,9 +341,7 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
|
|||||||
args.Gas = num
|
args.Gas = num
|
||||||
|
|
||||||
num = nil
|
num = nil
|
||||||
if ext.GasPrice == nil {
|
if ext.GasPrice != nil {
|
||||||
num = big.NewInt(0)
|
|
||||||
} else {
|
|
||||||
if num, err = numString(ext.GasPrice); err != nil {
|
if num, err = numString(ext.GasPrice); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user