cmd,eth enforce gas price of 0

This commit is contained in:
Bas van Kervel 2016-11-07 12:23:49 +01:00
parent 70448724e8
commit 9bb4635f70
22 changed files with 108 additions and 786 deletions

View File

@ -22,6 +22,8 @@ import (
"io"
"io/ioutil"
"math/big"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
@ -58,5 +60,6 @@ func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts {
}
return tx.WithSignature(signature)
},
GasPrice: new(big.Int),
}
}

View File

@ -207,9 +207,9 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
// Create the transaction, sign it and schedule it for execution
var rawTx *types.Transaction
if contract == nil {
rawTx = types.NewContractCreation(nonce, value, gasLimit, gasPrice, input)
rawTx = types.NewContractCreation(nonce, value, gasLimit, nil, input)
} else {
rawTx = types.NewTransaction(nonce, c.address, value, gasLimit, gasPrice, input)
rawTx = types.NewTransaction(nonce, c.address, value, gasLimit, nil, input)
}
if opts.Signer == nil {
return nil, errors.New("no signer to authorize the transaction with")

View File

@ -59,7 +59,7 @@ func TestWaitDeployed(t *testing.T) {
})
// Create the transaction.
tx := types.NewContractCreation(0, big.NewInt(0), test.gas, big.NewInt(1), common.FromHex(test.code))
tx := types.NewContractCreation(0, big.NewInt(0), test.gas, big.NewInt(0), common.FromHex(test.code))
tx, _ = tx.SignECDSA(testKey)
// Wait for it to get mined in the background.

View File

@ -116,7 +116,6 @@ participating.
utils.MaxPeersFlag,
utils.MaxPendingPeersFlag,
utils.EtherbaseFlag,
utils.GasPriceFlag,
utils.AutoDAGFlag,
utils.TargetGasLimitFlag,
utils.NATFlag,
@ -149,12 +148,6 @@ participating.
utils.MetricsEnabledFlag,
utils.FakePoWFlag,
utils.SolcPathFlag,
utils.GpoMinGasPriceFlag,
utils.GpoMaxGasPriceFlag,
utils.GpoFullBlockRatioFlag,
utils.GpobaseStepDownFlag,
utils.GpobaseStepUpFlag,
utils.GpobaseCorrectionFactorFlag,
utils.ExtraDataFlag,
utils.VoteAccountFlag,
utils.VoteAccountPasswordFlag,

View File

@ -134,17 +134,6 @@ var AppHelpFlagGroups = []flagGroup{
utils.NodeKeyHexFlag,
},
},
{
Name: "GAS PRICE ORACLE",
Flags: []cli.Flag{
utils.GpoMinGasPriceFlag,
utils.GpoMaxGasPriceFlag,
utils.GpoFullBlockRatioFlag,
utils.GpobaseStepDownFlag,
utils.GpobaseStepUpFlag,
utils.GpobaseCorrectionFactorFlag,
},
},
{
Name: "VIRTUAL MACHINE",
Flags: []cli.Flag{

View File

@ -169,11 +169,6 @@ var (
Usage: "Public address for block mining rewards (default = first account created)",
Value: "0",
}
GasPriceFlag = cli.StringFlag{
Name: "gasprice",
Usage: "Minimal gas price to accept for mining a transactions",
Value: common.Big0.String(),
}
ExtraDataFlag = cli.StringFlag{
Name: "extradata",
Usage: "Block extra data set by the miner (default = client version)",
@ -339,38 +334,6 @@ var (
Usage: "Solidity compiler command to be used",
Value: "solc",
}
// Gas price oracle settings
GpoMinGasPriceFlag = cli.StringFlag{
Name: "gpomin",
Usage: "Minimum suggested gas price",
Value: new(big.Int).Mul(big.NewInt(20), common.Shannon).String(),
}
GpoMaxGasPriceFlag = cli.StringFlag{
Name: "gpomax",
Usage: "Maximum suggested gas price",
Value: new(big.Int).Mul(big.NewInt(500), common.Shannon).String(),
}
GpoFullBlockRatioFlag = cli.IntFlag{
Name: "gpofull",
Usage: "Full block threshold for gas price calculation (%)",
Value: 80,
}
GpobaseStepDownFlag = cli.IntFlag{
Name: "gpobasedown",
Usage: "Suggested gas price base step down ratio (1/1000)",
Value: 10,
}
GpobaseStepUpFlag = cli.IntFlag{
Name: "gpobaseup",
Usage: "Suggested gas price base step up ratio (1/1000)",
Value: 100,
}
GpobaseCorrectionFactorFlag = cli.IntFlag{
Name: "gpobasecf",
Usage: "Suggested gas price base correction factor (%)",
Value: 110,
}
// Quorum flags
VoteAccountFlag = cli.StringFlag{
Name: "voteaccount",
@ -688,27 +651,20 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
}
ethConf := &eth.Config{
Etherbase: MakeEtherbase(stack.AccountManager(), ctx),
ChainConfig: MakeChainConfig(ctx, stack),
SingleBlockMaker: ctx.GlobalBool(SingleBlockMakerFlag.Name),
DatabaseCache: ctx.GlobalInt(CacheFlag.Name),
DatabaseHandles: MakeDatabaseHandles(),
NetworkId: ctx.GlobalInt(NetworkIdFlag.Name),
ExtraData: MakeMinerExtra(extra, ctx),
NatSpec: ctx.GlobalBool(NatspecEnabledFlag.Name),
DocRoot: ctx.GlobalString(DocRootFlag.Name),
EnableJit: jitEnabled,
ForceJit: ctx.GlobalBool(VMForceJitFlag.Name),
GasPrice: common.String2Big(ctx.GlobalString(GasPriceFlag.Name)),
GpoMinGasPrice: common.String2Big(ctx.GlobalString(GpoMinGasPriceFlag.Name)),
GpoMaxGasPrice: common.String2Big(ctx.GlobalString(GpoMaxGasPriceFlag.Name)),
GpoFullBlockRatio: ctx.GlobalInt(GpoFullBlockRatioFlag.Name),
GpobaseStepDown: ctx.GlobalInt(GpobaseStepDownFlag.Name),
GpobaseStepUp: ctx.GlobalInt(GpobaseStepUpFlag.Name),
GpobaseCorrectionFactor: ctx.GlobalInt(GpobaseCorrectionFactorFlag.Name),
SolcPath: ctx.GlobalString(SolcPathFlag.Name),
VoteMinBlockTime: uint(ctx.GlobalInt(VoteMinBlockTimeFlag.Name)),
VoteMaxBlockTime: uint(ctx.GlobalInt(VoteMaxBlockTimeFlag.Name)),
Etherbase: MakeEtherbase(stack.AccountManager(), ctx),
ChainConfig: MakeChainConfig(ctx, stack),
SingleBlockMaker: ctx.GlobalBool(SingleBlockMakerFlag.Name),
DatabaseCache: ctx.GlobalInt(CacheFlag.Name),
DatabaseHandles: MakeDatabaseHandles(),
NetworkId: ctx.GlobalInt(NetworkIdFlag.Name),
ExtraData: MakeMinerExtra(extra, ctx),
NatSpec: ctx.GlobalBool(NatspecEnabledFlag.Name),
DocRoot: ctx.GlobalString(DocRootFlag.Name),
EnableJit: jitEnabled,
ForceJit: ctx.GlobalBool(VMForceJitFlag.Name),
SolcPath: ctx.GlobalString(SolcPathFlag.Name),
VoteMinBlockTime: uint(ctx.GlobalInt(VoteMinBlockTimeFlag.Name)),
VoteMaxBlockTime: uint(ctx.GlobalInt(VoteMaxBlockTimeFlag.Name)),
}
// Override any default configs in dev mode or the test net
@ -728,9 +684,6 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
case ctx.GlobalBool(DevModeFlag.Name):
ethConf.Genesis = core.OlympicGenesisBlock()
if !ctx.GlobalIsSet(GasPriceFlag.Name) {
ethConf.GasPrice = new(big.Int)
}
ethConf.PowTest = true
}
// Override any global options pertaining to the Ethereum protocol

View File

@ -223,7 +223,6 @@ func (be *registryAPIBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasSt
to = common.HexToAddress(toStr)
value = common.Big(valueStr)
gas *big.Int
price *big.Int
data []byte
contractCreation bool
)
@ -234,12 +233,6 @@ func (be *registryAPIBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasSt
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
@ -252,9 +245,9 @@ func (be *registryAPIBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasSt
var tx *types.Transaction
if contractCreation {
tx = types.NewContractCreation(nonce, value, gas, price, data)
tx = types.NewContractCreation(nonce, value, gas, nil, data)
} else {
tx = types.NewTransaction(nonce, to, value, gas, price, data)
tx = types.NewTransaction(nonce, to, value, gas, nil, data)
}
signature, err := be.am.SignEthereum(from, tx.SigHash().Bytes())

View File

@ -3,8 +3,6 @@ package quorum
import (
"time"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
@ -64,7 +62,6 @@ func (ps *pendingState) applyTransactions(txs *types.TransactionsByPriorityAndNo
var (
lowGasTxs types.Transactions
failedTxs types.Transactions
gasPrice = new(big.Int).Mul(big.NewInt(20), common.Shannon)
)
var coalescedLogs vm.Logs
@ -78,14 +75,6 @@ func (ps *pendingState) applyTransactions(txs *types.TransactionsByPriorityAndNo
// during transaction acceptance is the transaction pool.
from, _ := tx.From()
// Ignore any transactions (and accounts subsequently) with low gas limits
if tx.GasPrice().Cmp(gasPrice) < 0 && !ps.ownedAccounts.Has(from) {
// Pop the current low-priced transaction without shifting in the next from the account
glog.V(logger.Info).Infof("Transaction (%x) below gas price (tx=%v ask=%v). All sequential txs from this address(%x) will be ignored\n", tx.Hash().Bytes()[:4], common.CurrencyToString(tx.GasPrice()), common.CurrencyToString(gasPrice), from[:4])
lowGasTxs = append(lowGasTxs, tx)
txs.Pop()
continue
}
// Start executing the transaction
ps.state.StartRecord(tx.Hash(), common.Hash{}, 0)

View File

@ -85,14 +85,13 @@ type CreateBlock struct {
// Note, don't forget to call Start.
func NewBlockVoting(bc *core.BlockChain, chainConfig *core.ChainConfig, txpool *core.TxPool, mux *event.TypeMux, db ethdb.Database, accountMgr *accounts.Manager, isSynchronised bool) *BlockVoting {
bv := &BlockVoting{
bc: bc,
cc: chainConfig,
txpool: txpool,
mux: mux,
db: db,
am: accountMgr,
synced: isSynchronised,
gasPrice: new(big.Int).Mul(big.NewInt(10), common.Shannon),
bc: bc,
cc: chainConfig,
txpool: txpool,
mux: mux,
db: db,
am: accountMgr,
synced: isSynchronised,
}
return bv

View File

@ -19,6 +19,7 @@ package core
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@ -87,6 +88,11 @@ func ApplyTransaction(config *ChainConfig, bc *BlockChain, gp *GasPool, publicSt
if !tx.IsPrivate() {
privateState = publicState
}
if tx.GasPrice() != nil && tx.GasPrice().Cmp(common.Big0) > 0 {
return nil, nil, nil, ErrInvalidGasPrice
}
_, gas, err := ApplyMessage(NewEnv(publicState, privateState, config, bc, tx, header, cfg), tx, gp)
if err != nil {
return nil, nil, nil, err

View File

@ -33,7 +33,7 @@ func TestStrictTxListAdd(t *testing.T) {
txs := make(types.Transactions, 1024)
for i := 0; i < len(txs); i++ {
txs[i] = transaction(uint64(i), new(big.Int), key)
txs[i] = transaction(uint64(i), new(big.Int), new(big.Int), key)
}
// Insert the transactions in a random order
list := newTxList(true)

View File

@ -37,13 +37,12 @@ var (
// Transaction Pool Errors
ErrInvalidSender = errors.New("Invalid sender")
ErrNonce = errors.New("Nonce too low")
ErrCheap = errors.New("Gas price too low for acceptance")
ErrBalance = errors.New("Insufficient balance")
ErrNonExistentAccount = errors.New("Account does not exist or account balance too low")
ErrInvalidGasPrice = errors.New("Gas price not 0")
ErrInsufficientFunds = errors.New("Insufficient funds for gas * price + value")
ErrIntrinsicGas = errors.New("Intrinsic gas too low")
ErrGasLimit = errors.New("Exceeds block gas limit")
ErrNegativeValue = errors.New("Negative value")
ErrNonExistentAccount = errors.New("Account doesn't exist")
)
var (
@ -69,7 +68,6 @@ type TxPool struct {
currentState stateFn // The state function which will allow us to do some pre checks
pendingState *state.ManagedState
gasLimit func() *big.Int // The current gas limit function callback
minGasPrice *big.Int
eventMux *event.TypeMux
events event.Subscription
localTx *txSet
@ -96,10 +94,9 @@ func NewTxPool(config *ChainConfig, eventMux *event.TypeMux, currentStateFn stat
eventMux: eventMux,
currentState: currentStateFn,
gasLimit: gasLimitFn,
minGasPrice: new(big.Int),
pendingState: nil,
localTx: newTxSet(),
events: eventMux.Subscribe(ChainHeadEvent{}, GasPriceChanged{}, RemovedTransactionEvent{}),
events: eventMux.Subscribe(ChainHeadEvent{}, RemovedTransactionEvent{}),
quit: make(chan struct{}),
}
@ -126,10 +123,6 @@ func (pool *TxPool) eventLoop() {
pool.resetState()
pool.mu.Unlock()
case GasPriceChanged:
pool.mu.Lock()
pool.minGasPrice = ev.Price
pool.mu.Unlock()
case RemovedTransactionEvent:
pool.AddBatch(ev.Txs)
}
@ -151,8 +144,7 @@ func (pool *TxPool) resetState() {
// validate the pool of pending transactions, this will remove
// any transactions that have been included in the block or
// have been invalidated because of another transaction (e.g.
// higher gas price)
// have been invalidated because of another transaction.
pool.demoteUnexecutables()
// Update all accounts to the latest known pending nonce
@ -231,8 +223,7 @@ func (pool *TxPool) Pending() map[common.Address]types.Transactions {
return pending
}
// SetLocal marks a transaction as local, skipping gas price
// check against local miner minimum in the future
// SetLocal marks a transaction as local.
func (pool *TxPool) SetLocal(tx *types.Transaction) {
pool.mu.Lock()
defer pool.mu.Unlock()
@ -242,10 +233,10 @@ func (pool *TxPool) SetLocal(tx *types.Transaction) {
// 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
// due to dual state balances of private accounts cannot be determined.
// only accept transactions with a gas price of 0
if tx.GasPrice().Cmp(common.Big0) != 0 {
return ErrInvalidGasPrice
}
currentState, _, err := pool.currentState()

View File

@ -31,8 +31,8 @@ import (
"github.com/ethereum/go-ethereum/event"
)
func transaction(nonce uint64, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
tx, _ := types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, big.NewInt(1), nil).SignECDSA(key)
func transaction(nonce uint64, gasPrice, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
tx, _ := types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, gasPrice, nil).SignECDSA(key)
return tx
}
@ -50,11 +50,7 @@ func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
func TestInvalidTransactions(t *testing.T) {
pool, key := setupTxPool()
tx := transaction(0, big.NewInt(100), key)
if err := pool.Add(tx); err != ErrNonExistentAccount {
t.Error("expected", ErrNonExistentAccount)
}
tx := transaction(0, big.NewInt(0), big.NewInt(100), key)
from, _ := tx.From()
currentState, _, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1))
@ -70,26 +66,15 @@ func TestInvalidTransactions(t *testing.T) {
currentState.SetNonce(from, 1)
currentState.AddBalance(from, big.NewInt(0xffffffffffffff))
tx = transaction(0, big.NewInt(100000), key)
tx = transaction(0, big.NewInt(0), big.NewInt(100000), key)
if err := pool.Add(tx); err != ErrNonce {
t.Error("expected", ErrNonce)
}
tx = transaction(1, big.NewInt(100000), key)
pool.minGasPrice = big.NewInt(1000)
if err := pool.Add(tx); err != ErrCheap {
t.Error("expected", ErrCheap, "got", err)
}
pool.SetLocal(tx)
if err := pool.Add(tx); err != nil {
t.Error("expected", nil, "got", err)
t.Error("expected", ErrNonce, "got", err)
}
}
func TestTransactionQueue(t *testing.T) {
pool, key := setupTxPool()
tx := transaction(0, big.NewInt(100), key)
tx := transaction(0, big.NewInt(0), big.NewInt(100), key)
from, _ := tx.From()
currentState, _, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1000))
@ -100,7 +85,7 @@ func TestTransactionQueue(t *testing.T) {
t.Error("expected valid txs to be 1 is", len(pool.pending))
}
tx = transaction(1, big.NewInt(100), key)
tx = transaction(1, big.NewInt(0), big.NewInt(100), key)
from, _ = tx.From()
currentState.SetNonce(from, 2)
pool.enqueueTx(tx.Hash(), tx)
@ -114,9 +99,9 @@ func TestTransactionQueue(t *testing.T) {
}
pool, key = setupTxPool()
tx1 := transaction(0, big.NewInt(100), key)
tx2 := transaction(10, big.NewInt(100), key)
tx3 := transaction(11, big.NewInt(100), key)
tx1 := transaction(0, big.NewInt(0), big.NewInt(100), key)
tx2 := transaction(10, big.NewInt(0), big.NewInt(100), key)
tx3 := transaction(11, big.NewInt(0), big.NewInt(100), key)
from, _ = tx1.From()
currentState, _, _ = pool.currentState()
currentState.AddBalance(from, big.NewInt(1000))
@ -136,7 +121,7 @@ func TestTransactionQueue(t *testing.T) {
func TestRemoveTx(t *testing.T) {
pool, key := setupTxPool()
tx := transaction(0, big.NewInt(100), key)
tx := transaction(0, big.NewInt(0), big.NewInt(100), key)
from, _ := tx.From()
currentState, _, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1))
@ -158,18 +143,6 @@ func TestRemoveTx(t *testing.T) {
}
}
func TestNegativeValue(t *testing.T) {
pool, key := setupTxPool()
tx, _ := types.NewTransaction(0, common.Address{}, big.NewInt(-1), big.NewInt(100), big.NewInt(1), nil).SignECDSA(key)
from, _ := tx.From()
currentState, _, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1))
if err := pool.Add(tx); err != ErrNegativeValue {
t.Error("expected", ErrNegativeValue, "got", err)
}
}
func TestTransactionChainFork(t *testing.T) {
pool, key := setupTxPool()
addr := crypto.PubkeyToAddress(key.PublicKey)
@ -183,7 +156,7 @@ func TestTransactionChainFork(t *testing.T) {
}
resetState()
tx := transaction(0, big.NewInt(100000), key)
tx := transaction(0, new(big.Int), big.NewInt(100000), key)
if err := pool.add(tx); err != nil {
t.Error("didn't expect error", err)
}
@ -196,60 +169,12 @@ func TestTransactionChainFork(t *testing.T) {
}
}
func TestTransactionDoubleNonce(t *testing.T) {
pool, key := setupTxPool()
addr := crypto.PubkeyToAddress(key.PublicKey)
resetState := func() {
db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, db)
pool.currentState = func() (*state.StateDB, *state.StateDB, error) { return statedb, statedb, nil }
currentState, _, _ := pool.currentState()
currentState.AddBalance(addr, big.NewInt(100000000000000))
pool.resetState()
}
resetState()
tx1, _ := types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(100000), big.NewInt(1), nil).SignECDSA(key)
tx2, _ := types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(2), nil).SignECDSA(key)
tx3, _ := types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(1), nil).SignECDSA(key)
// Add the first two transaction, ensure higher priced stays only
if err := pool.add(tx1); err != nil {
t.Error("didn't expect error", err)
}
if err := pool.add(tx2); err != nil {
t.Error("didn't expect error", err)
}
pool.promoteExecutables()
if pool.pending[addr].Len() != 1 {
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
}
if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() {
t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash())
}
// Add the thid transaction and ensure it's not saved (smaller price)
if err := pool.add(tx3); err != nil {
t.Error("didn't expect error", err)
}
pool.promoteExecutables()
if pool.pending[addr].Len() != 1 {
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
}
if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() {
t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash())
}
// Ensure the total transaction count is correct
if len(pool.all) != 1 {
t.Error("expected 1 total transactions, got", len(pool.all))
}
}
func TestMissingNonce(t *testing.T) {
pool, key := setupTxPool()
addr := crypto.PubkeyToAddress(key.PublicKey)
currentState, _, _ := pool.currentState()
currentState.AddBalance(addr, big.NewInt(100000000000000))
tx := transaction(1, big.NewInt(100000), key)
tx := transaction(1, new(big.Int), big.NewInt(100000), key)
if err := pool.add(tx); err != nil {
t.Error("didn't expect error", err)
}
@ -272,7 +197,7 @@ func TestNonceRecovery(t *testing.T) {
currentState.SetNonce(addr, n)
currentState.AddBalance(addr, big.NewInt(100000000000000))
pool.resetState()
tx := transaction(n, big.NewInt(100000), key)
tx := transaction(n, new(big.Int), big.NewInt(100000), key)
if err := pool.Add(tx); err != nil {
t.Error(err)
}
@ -286,7 +211,7 @@ func TestNonceRecovery(t *testing.T) {
func TestRemovedTxEvent(t *testing.T) {
pool, key := setupTxPool()
tx := transaction(0, big.NewInt(1000000), key)
tx := transaction(0, big.NewInt(0), big.NewInt(1000000), key)
from, _ := tx.From()
currentState, _, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1000000000000))
@ -300,157 +225,19 @@ func TestRemovedTxEvent(t *testing.T) {
}
}
// Tests that if an account runs out of funds, any pending and queued transactions
// are dropped.
func TestTransactionDropping(t *testing.T) {
// Create a test account and fund it
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
state, _, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000))
// Add some pending and some queued transactions
var (
tx0 = transaction(0, big.NewInt(100), key)
tx1 = transaction(1, big.NewInt(200), key)
tx10 = transaction(10, big.NewInt(100), key)
tx11 = transaction(11, big.NewInt(200), key)
)
pool.promoteTx(account, tx0.Hash(), tx0)
pool.promoteTx(account, tx1.Hash(), tx1)
pool.enqueueTx(tx10.Hash(), tx10)
pool.enqueueTx(tx11.Hash(), tx11)
// Check that pre and post validations leave the pool as is
if pool.pending[account].Len() != 2 {
t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 2)
}
if pool.queue[account].Len() != 2 {
t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 2)
}
if len(pool.all) != 4 {
t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 4)
}
pool.resetState()
if pool.pending[account].Len() != 2 {
t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 2)
}
if pool.queue[account].Len() != 2 {
t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 2)
}
if len(pool.all) != 4 {
t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 4)
}
// Reduce the balance of the account, and check that invalidated transactions are dropped
state.AddBalance(account, big.NewInt(-750))
pool.resetState()
if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok {
t.Errorf("funded pending transaction missing: %v", tx0)
}
if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; ok {
t.Errorf("out-of-fund pending transaction present: %v", tx1)
}
if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok {
t.Errorf("funded queued transaction missing: %v", tx10)
}
if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; ok {
t.Errorf("out-of-fund queued transaction present: %v", tx11)
}
if len(pool.all) != 2 {
t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 2)
}
}
// Tests that if a transaction is dropped from the current pending pool (e.g. out
// of fund), all consecutive (still valid, but not executable) transactions are
// postponed back into the future queue to prevent broadcasting them.
func TestTransactionPostponing(t *testing.T) {
// Create a test account and fund it
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
state, _, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000))
// Add a batch consecutive pending transactions for validation
txns := []*types.Transaction{}
for i := 0; i < 100; i++ {
var tx *types.Transaction
if i%2 == 0 {
tx = transaction(uint64(i), big.NewInt(100), key)
} else {
tx = transaction(uint64(i), big.NewInt(500), key)
}
pool.promoteTx(account, tx.Hash(), tx)
txns = append(txns, tx)
}
// Check that pre and post validations leave the pool as is
if pool.pending[account].Len() != len(txns) {
t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), len(txns))
}
if len(pool.queue) != 0 {
t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 0)
}
if len(pool.all) != len(txns) {
t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txns))
}
pool.resetState()
if pool.pending[account].Len() != len(txns) {
t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), len(txns))
}
if len(pool.queue) != 0 {
t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 0)
}
if len(pool.all) != len(txns) {
t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txns))
}
// Reduce the balance of the account, and check that transactions are reorganised
state.AddBalance(account, big.NewInt(-750))
pool.resetState()
if _, ok := pool.pending[account].txs.items[txns[0].Nonce()]; !ok {
t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txns[0])
}
if _, ok := pool.queue[account].txs.items[txns[0].Nonce()]; ok {
t.Errorf("tx %d: valid and funded transaction present in future queue: %v", 0, txns[0])
}
for i, tx := range txns[1:] {
if i%2 == 1 {
if _, ok := pool.pending[account].txs.items[tx.Nonce()]; ok {
t.Errorf("tx %d: valid but future transaction present in pending pool: %v", i+1, tx)
}
if _, ok := pool.queue[account].txs.items[tx.Nonce()]; !ok {
t.Errorf("tx %d: valid but future transaction missing from future queue: %v", i+1, tx)
}
} else {
if _, ok := pool.pending[account].txs.items[tx.Nonce()]; ok {
t.Errorf("tx %d: out-of-fund transaction present in pending pool: %v", i+1, tx)
}
if _, ok := pool.queue[account].txs.items[tx.Nonce()]; ok {
t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", i+1, tx)
}
}
}
if len(pool.all) != len(txns)/2 {
t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txns)/2)
}
}
// Tests that if the transaction count belonging to a single account goes above
// some threshold, the higher transactions are dropped to prevent DOS attacks.
func TestTransactionQueueAccountLimiting(t *testing.T) {
// Create a test account and fund it
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := transaction(0, new(big.Int), big.NewInt(0), key).From()
state, _, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
// Keep queuing up transactions and make sure all above a limit are dropped
for i := uint64(1); i <= maxQueuedPerAccount+5; i++ {
if err := pool.Add(transaction(i, big.NewInt(100000), key)); err != nil {
if err := pool.Add(transaction(i, new(big.Int), big.NewInt(100000), key)); err != nil {
t.Fatalf("tx %d: failed to add transaction: %v", i, err)
}
if len(pool.pending) != 0 {
@ -501,7 +288,7 @@ func TestTransactionQueueGlobalLimiting(t *testing.T) {
key := keys[rand.Intn(len(keys))]
addr := crypto.PubkeyToAddress(key.PublicKey)
txs = append(txs, transaction(nonces[addr]+1, big.NewInt(100000), key))
txs = append(txs, transaction(nonces[addr]+1, new(big.Int), big.NewInt(100000), key))
nonces[addr]++
}
// Import the batch and verify that limits have been enforced
@ -531,14 +318,14 @@ func TestTransactionQueueTimeLimiting(t *testing.T) {
// Create a test account and fund it
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := transaction(0, new(big.Int), big.NewInt(0), key).From()
state, _, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
// Queue up a batch of transactions
for i := uint64(1); i <= maxQueuedPerAccount; i++ {
if err := pool.Add(transaction(i, big.NewInt(100000), key)); err != nil {
if err := pool.Add(transaction(i, new(big.Int), big.NewInt(100000), key)); err != nil {
t.Fatalf("tx %d: failed to add transaction: %v", i, err)
}
}
@ -555,14 +342,14 @@ func TestTransactionQueueTimeLimiting(t *testing.T) {
func TestTransactionPendingLimiting(t *testing.T) {
// Create a test account and fund it
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := transaction(0, new(big.Int), big.NewInt(0), key).From()
state, _, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
// Keep queuing up transactions and make sure all above a limit are dropped
for i := uint64(0); i < maxQueuedPerAccount+5; i++ {
if err := pool.Add(transaction(i, big.NewInt(100000), key)); err != nil {
if err := pool.Add(transaction(i, new(big.Int), big.NewInt(100000), key)); err != nil {
t.Fatalf("tx %d: failed to add transaction: %v", i, err)
}
if pool.pending[account].Len() != int(i)+1 {
@ -585,24 +372,24 @@ func TestTransactionPendingLimitingEquivalency(t *testing.T) { testTransactionLi
func testTransactionLimitingEquivalency(t *testing.T, origin uint64) {
// Add a batch of transactions to a pool one by one
pool1, key1 := setupTxPool()
account1, _ := transaction(0, big.NewInt(0), key1).From()
account1, _ := transaction(0, new(big.Int), big.NewInt(0), key1).From()
state1, _, _ := pool1.currentState()
state1.AddBalance(account1, big.NewInt(1000000))
for i := uint64(0); i < maxQueuedPerAccount+5; i++ {
if err := pool1.Add(transaction(origin+i, big.NewInt(100000), key1)); err != nil {
if err := pool1.Add(transaction(origin+i, new(big.Int), big.NewInt(100000), key1)); err != nil {
t.Fatalf("tx %d: failed to add transaction: %v", i, err)
}
}
// Add a batch of transactions to a pool in one big batch
pool2, key2 := setupTxPool()
account2, _ := transaction(0, big.NewInt(0), key2).From()
account2, _ := transaction(0, new(big.Int), big.NewInt(0), key2).From()
state2, _, _ := pool2.currentState()
state2.AddBalance(account2, big.NewInt(1000000))
txns := []*types.Transaction{}
for i := uint64(0); i < maxQueuedPerAccount+5; i++ {
txns = append(txns, transaction(origin+i, big.NewInt(100000), key2))
txns = append(txns, transaction(origin+i, new(big.Int), big.NewInt(100000), key2))
}
pool2.AddBatch(txns)
@ -648,7 +435,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) {
for _, key := range keys {
addr := crypto.PubkeyToAddress(key.PublicKey)
for j := 0; j < int(maxPendingTotal)/len(keys)*2; j++ {
txs = append(txs, transaction(nonces[addr], big.NewInt(100000), key))
txs = append(txs, transaction(nonces[addr], new(big.Int), big.NewInt(100000), key))
nonces[addr]++
}
}
@ -694,7 +481,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) {
for _, key := range keys {
addr := crypto.PubkeyToAddress(key.PublicKey)
for j := 0; j < int(minPendingPerAccount)*2; j++ {
txs = append(txs, transaction(nonces[addr], big.NewInt(100000), key))
txs = append(txs, transaction(nonces[addr], new(big.Int), big.NewInt(100000), key))
nonces[addr]++
}
}
@ -717,12 +504,12 @@ func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 1
func benchmarkPendingDemotion(b *testing.B, size int) {
// Add a batch of transactions to a pool one by one
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := transaction(0, new(big.Int), big.NewInt(0), key).From()
state, _, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
for i := 0; i < size; i++ {
tx := transaction(uint64(i), big.NewInt(100000), key)
tx := transaction(uint64(i), new(big.Int), big.NewInt(100000), key)
pool.promoteTx(account, tx.Hash(), tx)
}
// Benchmark the speed of pool validation
@ -741,12 +528,12 @@ func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 1
func benchmarkFuturePromotion(b *testing.B, size int) {
// Add a batch of transactions to a pool one by one
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := transaction(0, new(big.Int), big.NewInt(0), key).From()
state, _, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
for i := 0; i < size; i++ {
tx := transaction(uint64(1+i), big.NewInt(100000), key)
tx := transaction(uint64(1+i), new(big.Int), big.NewInt(100000), key)
pool.enqueueTx(tx.Hash(), tx)
}
// Benchmark the speed of pool validation
@ -760,13 +547,13 @@ func benchmarkFuturePromotion(b *testing.B, size int) {
func BenchmarkPoolInsert(b *testing.B) {
// Generate a batch of transactions to enqueue into the pool
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := transaction(0, new(big.Int), big.NewInt(0), key).From()
state, _, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
txs := make(types.Transactions, b.N)
for i := 0; i < b.N; i++ {
txs[i] = transaction(uint64(i), big.NewInt(100000), key)
txs[i] = transaction(uint64(i), new(big.Int), big.NewInt(100000), key)
}
// Benchmark importing the transactions into the queue
b.ResetTimer()
@ -783,7 +570,7 @@ func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 1
func benchmarkPoolBatchInsert(b *testing.B, size int) {
// Generate a batch of transactions to enqueue into the pool
pool, key := setupTxPool()
account, _ := transaction(0, big.NewInt(0), key).From()
account, _ := transaction(0, new(big.Int), big.NewInt(0), key).From()
state, _, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
@ -791,7 +578,7 @@ func benchmarkPoolBatchInsert(b *testing.B, size int) {
for i := 0; i < b.N; i++ {
batches[i] = make(types.Transactions, size)
for j := 0; j < size; j++ {
batches[i][j] = transaction(uint64(size*i+j), big.NewInt(100000), key)
batches[i][j] = transaction(uint64(size*i+j), new(big.Int), big.NewInt(100000), key)
}
}
// Benchmark importing the transactions into the queue

View File

@ -26,9 +26,8 @@ import (
"github.com/ethereum/go-ethereum/rlp"
)
// from bcValidBlockTest.json, "SimpleTx"
func TestBlockEncoding(t *testing.T) {
blockEnc := common.FromHex("f90260f901f9a083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f861f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1c0")
blockEnc := common.FromHex("f90260f901f9a083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a08bba9707f73a6c9801825706d0814d4ae310e4ff0a16fcd94e72174a176930e4a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f861f85f808082c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1c0")
var block Block
if err := rlp.DecodeBytes(blockEnc, &block); err != nil {
t.Fatal("decode error: ", err)
@ -39,18 +38,19 @@ func TestBlockEncoding(t *testing.T) {
t.Errorf("%s mismatch: got %v, want %v", f, got, want)
}
}
check("Difficulty", block.Difficulty(), big.NewInt(131072))
check("GasLimit", block.GasLimit(), big.NewInt(3141592))
check("GasUsed", block.GasUsed(), big.NewInt(21000))
check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1"))
check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498"))
check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017"))
check("Hash", block.Hash(), common.HexToHash("0a5843ac1cb04865017cb35a57b50b07084e5fcee39b5acadade33149f4fff9e"))
check("Hash", block.Hash(), common.HexToHash("655702f58f3497047c3c3be2ad131b653ac1141a3c1c0045c8fd3946e0d479f2"))
check("Nonce", block.Nonce(), uint64(0xa13a5a8c8f2bb1c4))
check("Time", block.Time(), big.NewInt(1426516743))
check("Size", block.Size(), common.StorageSize(len(blockEnc)))
tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), big.NewInt(50000), big.NewInt(10), nil)
tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), big.NewInt(50000), big.NewInt(0), nil)
tx1, _ = tx1.WithSignature(common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b11b"))
check("len(Transactions)", len(block.Transactions()), 1)
check("Transactions[0].Hash", block.Transactions()[0].Hash(), tx1.Hash())

View File

@ -80,7 +80,7 @@ func NewContractCreation(nonce uint64, amount, gasLimit, gasPrice *big.Int, data
Recipient: nil,
Amount: new(big.Int).Set(amount),
GasLimit: new(big.Int).Set(gasLimit),
Price: new(big.Int).Set(gasPrice),
Price: new(big.Int),
Payload: data,
R: new(big.Int),
S: new(big.Int),
@ -108,9 +108,6 @@ func NewTransaction(nonce uint64, to common.Address, amount, gasLimit, gasPrice
if gasLimit != nil {
d.GasLimit.Set(gasLimit)
}
if gasPrice != nil {
d.Price.Set(gasPrice)
}
return &Transaction{data: d}
}

View File

@ -45,7 +45,7 @@ var (
common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"),
big.NewInt(10),
big.NewInt(2000),
big.NewInt(1),
big.NewInt(0),
common.FromHex("5544"),
).WithSignature(
common.Hex2Bytes("98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a31c"),
@ -56,8 +56,8 @@ func TestTransactionSigHash(t *testing.T) {
if emptyTx.SigHash() != common.HexToHash("c775b99e7ad12f50d819fcd602390467e28141316969f4b57f0626f74fe3b386") {
t.Errorf("empty transaction hash mismatch, got %x", emptyTx.Hash())
}
if rightvrsTx.SigHash() != common.HexToHash("fe7a79529ed5f7c3375d06b26b186a8644e0e16c373d7a12be41c62d6042b77a") {
t.Errorf("RightVRS transaction hash mismatch, got %x", rightvrsTx.Hash())
if rightvrsTx.SigHash() != common.HexToHash("c75e06c2a1b4e254e869653871436fdfa752fd613152b474e6dd36b73a13dae2") {
t.Errorf("RightVRS transaction hash mismatch, got %x", rightvrsTx.SigHash())
}
}
@ -66,7 +66,7 @@ func TestTransactionEncode(t *testing.T) {
if err != nil {
t.Fatalf("encode error: %v", err)
}
should := common.FromHex("f86103018207d094b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a8255441ca098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa08887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3")
should := common.FromHex("f86103808207d094b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a8255441ca098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa08887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3")
if !bytes.Equal(txb, should) {
t.Errorf("encoded RLP mismatch, got %x", txb)
}

View File

@ -26,7 +26,6 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/ethapi"
@ -37,7 +36,6 @@ import (
// EthApiBackend implements ethapi.Backend for full nodes
type EthApiBackend struct {
eth *Ethereum
gpo *gasprice.GasPriceOracle
}
func (b *EthApiBackend) SetHead(number uint64) {
@ -177,7 +175,7 @@ func (b *EthApiBackend) ProtocolVersion() int {
}
func (b *EthApiBackend) SuggestPrice(ctx context.Context) (*big.Int, error) {
return b.gpo.SuggestPrice(), nil
return big.NewInt(0), nil
}
func (b *EthApiBackend) ChainDb() ethdb.Database {

View File

@ -20,7 +20,6 @@ package eth
import (
"errors"
"fmt"
"math/big"
"os"
"path/filepath"
"regexp"
@ -39,7 +38,6 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/ethapi"
@ -82,17 +80,9 @@ type Config struct {
ExtraData []byte
Etherbase common.Address
GasPrice *big.Int
MinerThreads int
SolcPath string
GpoMinGasPrice *big.Int
GpoMaxGasPrice *big.Int
GpoFullBlockRatio int
GpobaseStepDown int
GpobaseStepUp int
GpobaseCorrectionFactor int
EnableJit bool
ForceJit bool
@ -227,16 +217,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
return nil, err
}
gpoParams := &gasprice.GpoParams{
GpoMinGasPrice: config.GpoMinGasPrice,
GpoMaxGasPrice: config.GpoMaxGasPrice,
GpoFullBlockRatio: config.GpoFullBlockRatio,
GpobaseStepDown: config.GpobaseStepDown,
GpobaseStepUp: config.GpobaseStepUp,
GpobaseCorrectionFactor: config.GpobaseCorrectionFactor,
}
gpo := gasprice.NewGasPriceOracle(eth.blockchain, chainDb, eth.eventMux, gpoParams)
eth.apiBackend = &EthApiBackend{eth, gpo}
eth.apiBackend = &EthApiBackend{eth}
eth.blockVoting = quorum.NewBlockVoting(eth.blockchain, eth.chainConfig, eth.txPool, eth.eventMux, eth.chainDb, eth.accountManager, config.SingleBlockMaker)

View File

@ -1,229 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package gasprice
import (
"math/big"
"math/rand"
"sync"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
)
const (
gpoProcessPastBlocks = 100
// for testing
gpoDefaultBaseCorrectionFactor = 110
gpoDefaultMinGasPrice = 10000000000000
)
type blockPriceInfo struct {
baseGasPrice *big.Int
}
type GpoParams struct {
GpoMinGasPrice *big.Int
GpoMaxGasPrice *big.Int
GpoFullBlockRatio int
GpobaseStepDown int
GpobaseStepUp int
GpobaseCorrectionFactor int
}
// GasPriceOracle recommends gas prices based on the content of recent
// blocks.
type GasPriceOracle struct {
chain *core.BlockChain
db ethdb.Database
evmux *event.TypeMux
params *GpoParams
initOnce sync.Once
minPrice *big.Int
lastBaseMutex sync.Mutex
lastBase *big.Int
// state of listenLoop
blocks map[uint64]*blockPriceInfo
firstProcessed, lastProcessed uint64
minBase *big.Int
}
// NewGasPriceOracle returns a new oracle.
func NewGasPriceOracle(chain *core.BlockChain, db ethdb.Database, evmux *event.TypeMux, params *GpoParams) *GasPriceOracle {
minprice := params.GpoMinGasPrice
if minprice == nil {
minprice = big.NewInt(gpoDefaultMinGasPrice)
}
minbase := new(big.Int).Mul(minprice, big.NewInt(100))
if params.GpobaseCorrectionFactor > 0 {
minbase = minbase.Div(minbase, big.NewInt(int64(params.GpobaseCorrectionFactor)))
}
return &GasPriceOracle{
chain: chain,
db: db,
evmux: evmux,
params: params,
blocks: make(map[uint64]*blockPriceInfo),
minBase: minbase,
minPrice: minprice,
lastBase: minprice,
}
}
func (gpo *GasPriceOracle) init() {
gpo.initOnce.Do(func() {
gpo.processPastBlocks()
go gpo.listenLoop()
})
}
func (self *GasPriceOracle) processPastBlocks() {
last := int64(-1)
cblock := self.chain.CurrentBlock()
if cblock != nil {
last = int64(cblock.NumberU64())
}
first := int64(0)
if last > gpoProcessPastBlocks {
first = last - gpoProcessPastBlocks
}
self.firstProcessed = uint64(first)
for i := first; i <= last; i++ {
block := self.chain.GetBlockByNumber(uint64(i))
if block != nil {
self.processBlock(block)
}
}
}
func (self *GasPriceOracle) listenLoop() {
events := self.evmux.Subscribe(core.ChainEvent{}, core.ChainSplitEvent{})
defer events.Unsubscribe()
for event := range events.Chan() {
switch event := event.Data.(type) {
case core.ChainEvent:
self.processBlock(event.Block)
case core.ChainSplitEvent:
self.processBlock(event.Block)
}
}
}
func (self *GasPriceOracle) processBlock(block *types.Block) {
i := block.NumberU64()
if i > self.lastProcessed {
self.lastProcessed = i
}
lastBase := self.minPrice
bpl := self.blocks[i-1]
if bpl != nil {
lastBase = bpl.baseGasPrice
}
if lastBase == nil {
return
}
var corr int
lp := self.lowestPrice(block)
if lp == nil {
return
}
if lastBase.Cmp(lp) < 0 {
corr = self.params.GpobaseStepUp
} else {
corr = -self.params.GpobaseStepDown
}
crand := int64(corr * (900 + rand.Intn(201)))
newBase := new(big.Int).Mul(lastBase, big.NewInt(1000000+crand))
newBase.Div(newBase, big.NewInt(1000000))
if newBase.Cmp(self.minBase) < 0 {
newBase = self.minBase
}
bpi := self.blocks[i]
if bpi == nil {
bpi = &blockPriceInfo{}
self.blocks[i] = bpi
}
bpi.baseGasPrice = newBase
self.lastBaseMutex.Lock()
self.lastBase = newBase
self.lastBaseMutex.Unlock()
glog.V(logger.Detail).Infof("Processed block #%v, base price is %v\n", i, newBase.Int64())
}
// returns the lowers possible price with which a tx was or could have been included
func (self *GasPriceOracle) lowestPrice(block *types.Block) *big.Int {
gasUsed := big.NewInt(0)
receipts := core.GetBlockReceipts(self.db, block.Hash(), block.NumberU64())
if len(receipts) > 0 {
if cgu := receipts[len(receipts)-1].CumulativeGasUsed; cgu != nil {
gasUsed = receipts[len(receipts)-1].CumulativeGasUsed
}
}
if new(big.Int).Mul(gasUsed, big.NewInt(100)).Cmp(new(big.Int).Mul(block.GasLimit(),
big.NewInt(int64(self.params.GpoFullBlockRatio)))) < 0 {
// block is not full, could have posted a tx with MinGasPrice
return big.NewInt(0)
}
txs := block.Transactions()
if len(txs) == 0 {
return big.NewInt(0)
}
// block is full, find smallest gasPrice
minPrice := txs[0].GasPrice()
for i := 1; i < len(txs); i++ {
price := txs[i].GasPrice()
if price.Cmp(minPrice) < 0 {
minPrice = price
}
}
return minPrice
}
// SuggestPrice returns the recommended gas price.
func (self *GasPriceOracle) SuggestPrice() *big.Int {
self.init()
self.lastBaseMutex.Lock()
price := new(big.Int).Set(self.lastBase)
self.lastBaseMutex.Unlock()
price.Mul(price, big.NewInt(int64(self.params.GpobaseCorrectionFactor)))
price.Div(price, big.NewInt(100))
if price.Cmp(self.minPrice) < 0 {
price.Set(self.minPrice)
} else if self.params.GpoMaxGasPrice != nil && price.Cmp(self.params.GpoMaxGasPrice) > 0 {
price.Set(self.params.GpoMaxGasPrice)
}
return price
}

View File

@ -283,9 +283,9 @@ func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs
}
}
if args.To == nil {
tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), data)
tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), nil, data)
} else {
tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), data)
tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), nil, data)
}
signature, err := s.am.SignWithPassphrase(args.From, passwd, tx.SigHash().Bytes())
@ -558,6 +558,10 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
msg.gas = big.NewInt(50000000)
}
if msg.gasPrice.Cmp(common.Big0) != 0 {
msg.gasPrice = new(big.Int)
}
// Execute the call and return
vmenv, vmError, err := s.b.GetVMEnv(ctx, msg, state, header)
if err != nil {
@ -1086,9 +1090,9 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen
}
}
if args.To == nil {
tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), data)
tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), nil, data)
} else {
tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), data)
tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), nil, data)
}
signature, err := s.b.AccountManager().SignEthereum(args.From, tx.SigHash().Bytes())
@ -1206,9 +1210,9 @@ func (tx *Tx) UnmarshalJSON(b []byte) (err error) {
}
if req.To == nil {
tx.tx = types.NewContractCreation(tx.Nonce.Uint64(), tx.Value.BigInt(), tx.GasLimit.BigInt(), tx.GasPrice.BigInt(), data)
tx.tx = types.NewContractCreation(tx.Nonce.Uint64(), tx.Value.BigInt(), tx.GasLimit.BigInt(), nil, data)
} else {
tx.tx = types.NewTransaction(tx.Nonce.Uint64(), *tx.To, tx.Value.BigInt(), tx.GasLimit.BigInt(), tx.GasPrice.BigInt(), data)
tx.tx = types.NewTransaction(tx.Nonce.Uint64(), *tx.To, tx.Value.BigInt(), tx.GasLimit.BigInt(), nil, data)
}
return nil
@ -1263,9 +1267,9 @@ func (s *PublicTransactionPoolAPI) SignTransaction(ctx context.Context, args Sig
var tx *types.Transaction
if args.To == nil {
tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), nil, common.FromHex(args.Data))
} else {
tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), nil, common.FromHex(args.Data))
}
signedTx, err := s.sign(args.From, tx)
@ -1310,9 +1314,9 @@ func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, tx Tx, gasPrice,
var newTx *types.Transaction
if tx.tx.To() == nil {
newTx = types.NewContractCreation(tx.tx.Nonce(), tx.tx.Value(), gasLimit.BigInt(), gasPrice.BigInt(), tx.tx.Data())
newTx = types.NewContractCreation(tx.tx.Nonce(), tx.tx.Value(), gasLimit.BigInt(), nil, tx.tx.Data())
} else {
newTx = types.NewTransaction(tx.tx.Nonce(), *tx.tx.To(), tx.tx.Value(), gasLimit.BigInt(), gasPrice.BigInt(), tx.tx.Data())
newTx = types.NewTransaction(tx.tx.Nonce(), *tx.tx.To(), tx.tx.Value(), gasLimit.BigInt(), nil, tx.tx.Data())
}
if tx.tx.IsPrivate() {
newTx.SetPrivate()

View File

@ -22,34 +22,6 @@ import (
"testing"
)
func TestBcValidBlockTests(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcUncleHeaderValidityTests(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcUncleTests(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcForkUncleTests(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcForkUncle.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcInvalidHeaderTests(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
if err != nil {
@ -78,13 +50,6 @@ func TestBcForkBlockTests(t *testing.T) {
}
}
func TestBcForkStress(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcForkStressTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcTotalDifficulty(t *testing.T) {
// skip because these will fail due to selfish mining fix
t.Skip()
@ -95,20 +60,6 @@ func TestBcTotalDifficulty(t *testing.T) {
}
}
func TestBcWallet(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcWalletTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestBcGasPricer(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcGasPricerTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
// TODO: iterate over files once we got more than a few
func TestBcRandom(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, big.NewInt(10), filepath.Join(blockTestDir, "RandomTests/bl201507071825GO.json"), BlockSkipTests)
@ -127,35 +78,6 @@ func TestBcMultiChain(t *testing.T) {
}
}
func TestBcState(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, big.NewInt(10), filepath.Join(blockTestDir, "bcStateTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
// Homestead tests
func TestHomesteadBcValidBlockTests(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcValidBlockTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcUncleHeaderValidityTests(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcUncleHeaderValiditiy.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcUncleTests(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcUncleTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcInvalidHeaderTests(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcInvalidHeaderTest.json"), BlockSkipTests)
if err != nil {
@ -170,60 +92,6 @@ func TestHomesteadBcRPCAPITests(t *testing.T) {
}
}
func TestHomesteadBcForkStress(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcForkStressTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcTotalDifficulty(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcTotalDifficultyTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcWallet(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcWalletTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcGasPricer(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcGasPricerTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcMultiChain(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcMultiChainTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcState(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcStateTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcExploit(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcExploitTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcShanghaiLove(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcShanghaiLove.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestHomesteadBcSuicideIssue(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcSuicideIssue.json"), BlockSkipTests)
if err != nil {

View File

@ -25,7 +25,7 @@
{
"data" : "0x",
"gasLimit" : "0x44aa20",
"gasPrice" : "0x01",
"gasPrice" : "0x00",
"nonce" : "0x00",
"r" : "0x836bdd27c1abba1a55221bc86f6f048c9e364680eebf9f3ab9b6c7ae462b76ee",
"s" : "0x0c6fbd2f365de9e87436d2ac7635b709093038befc6ec9933ee936ab0b4a24b6",
@ -1512,4 +1512,4 @@
}
}
}
}
}