diff --git a/accounts/abi/bind/auth.go b/accounts/abi/bind/auth.go index cd6adc746..7845381d3 100644 --- a/accounts/abi/bind/auth.go +++ b/accounts/abi/bind/auth.go @@ -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), } } diff --git a/accounts/abi/bind/base.go b/accounts/abi/bind/base.go index 965f51e85..3ad6c83fb 100644 --- a/accounts/abi/bind/base.go +++ b/accounts/abi/bind/base.go @@ -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") diff --git a/accounts/abi/bind/util_test.go b/accounts/abi/bind/util_test.go index 192fa4f4c..ca2a1c37d 100644 --- a/accounts/abi/bind/util_test.go +++ b/accounts/abi/bind/util_test.go @@ -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. diff --git a/cmd/geth/main.go b/cmd/geth/main.go index c04fdaafa..7ed1ba232 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -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, diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go index 841e1c87a..7a0c4c809 100644 --- a/cmd/geth/usage.go +++ b/cmd/geth/usage.go @@ -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{ diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 0b8d9ce46..d7465d5f8 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -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 := ð.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 diff --git a/common/registrar/ethreg/api.go b/common/registrar/ethreg/api.go index 5f7726158..e94ce80a5 100644 --- a/common/registrar/ethreg/api.go +++ b/common/registrar/ethreg/api.go @@ -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()) diff --git a/core/quorum/block_maker.go b/core/quorum/block_maker.go index a4bcb7fe4..832d3d1f5 100755 --- a/core/quorum/block_maker.go +++ b/core/quorum/block_maker.go @@ -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) diff --git a/core/quorum/block_voting.go b/core/quorum/block_voting.go index 57d9da864..f3830c9c8 100755 --- a/core/quorum/block_voting.go +++ b/core/quorum/block_voting.go @@ -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 diff --git a/core/state_processor.go b/core/state_processor.go index 19340dad5..dcdad1b19 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -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 diff --git a/core/tx_list_test.go b/core/tx_list_test.go index 92b211937..33ceb6a2e 100644 --- a/core/tx_list_test.go +++ b/core/tx_list_test.go @@ -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) diff --git a/core/tx_pool.go b/core/tx_pool.go index a926de2d9..2535609c7 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -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() diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go index 414fdd608..ce9f090ff 100644 --- a/core/tx_pool_test.go +++ b/core/tx_pool_test.go @@ -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 diff --git a/core/types/block_test.go b/core/types/block_test.go index ac7f17c0d..7200919bb 100644 --- a/core/types/block_test.go +++ b/core/types/block_test.go @@ -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()) diff --git a/core/types/transaction.go b/core/types/transaction.go index ab97302b2..3cb12768f 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -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} } diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index 24b905ba3..abbeae603 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -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) } diff --git a/eth/api_backend.go b/eth/api_backend.go index e3b5fd39e..309fe2160 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -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 { diff --git a/eth/backend.go b/eth/backend.go index 79dd78735..9ce8eeded 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -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) diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go deleted file mode 100644 index eb2df4a96..000000000 --- a/eth/gasprice/gasprice.go +++ /dev/null @@ -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 . - -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 -} diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index e7dbd2af0..a18ced9d8 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -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() diff --git a/tests/block_test.go b/tests/block_test.go index 535605180..4534e76bf 100644 --- a/tests/block_test.go +++ b/tests/block_test.go @@ -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 { diff --git a/tests/files/BlockchainTests/Homestead/bcShanghaiLove.json b/tests/files/BlockchainTests/Homestead/bcShanghaiLove.json index acf1f4737..ef7a1cb78 100644 --- a/tests/files/BlockchainTests/Homestead/bcShanghaiLove.json +++ b/tests/files/BlockchainTests/Homestead/bcShanghaiLove.json @@ -25,7 +25,7 @@ { "data" : "0x", "gasLimit" : "0x44aa20", - "gasPrice" : "0x01", + "gasPrice" : "0x00", "nonce" : "0x00", "r" : "0x836bdd27c1abba1a55221bc86f6f048c9e364680eebf9f3ab9b6c7ae462b76ee", "s" : "0x0c6fbd2f365de9e87436d2ac7635b709093038befc6ec9933ee936ab0b4a24b6", @@ -1512,4 +1512,4 @@ } } } -} \ No newline at end of file +}