mirror of https://github.com/poanetwork/quorum.git
Merge pull request #4 from bas-vk/zero-gasprice
cmd,eth enforce gas price of 0
This commit is contained in:
commit
b545f51c3c
|
@ -22,6 +22,8 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
@ -58,5 +60,6 @@ func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts {
|
||||||
}
|
}
|
||||||
return tx.WithSignature(signature)
|
return tx.WithSignature(signature)
|
||||||
},
|
},
|
||||||
|
GasPrice: new(big.Int),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,9 +207,9 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
|
||||||
// Create the transaction, sign it and schedule it for execution
|
// Create the transaction, sign it and schedule it for execution
|
||||||
var rawTx *types.Transaction
|
var rawTx *types.Transaction
|
||||||
if contract == nil {
|
if contract == nil {
|
||||||
rawTx = types.NewContractCreation(nonce, value, gasLimit, gasPrice, input)
|
rawTx = types.NewContractCreation(nonce, value, gasLimit, nil, input)
|
||||||
} else {
|
} 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 {
|
if opts.Signer == nil {
|
||||||
return nil, errors.New("no signer to authorize the transaction with")
|
return nil, errors.New("no signer to authorize the transaction with")
|
||||||
|
|
|
@ -59,7 +59,7 @@ func TestWaitDeployed(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create the transaction.
|
// 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)
|
tx, _ = tx.SignECDSA(testKey)
|
||||||
|
|
||||||
// Wait for it to get mined in the background.
|
// Wait for it to get mined in the background.
|
||||||
|
|
|
@ -116,7 +116,6 @@ participating.
|
||||||
utils.MaxPeersFlag,
|
utils.MaxPeersFlag,
|
||||||
utils.MaxPendingPeersFlag,
|
utils.MaxPendingPeersFlag,
|
||||||
utils.EtherbaseFlag,
|
utils.EtherbaseFlag,
|
||||||
utils.GasPriceFlag,
|
|
||||||
utils.AutoDAGFlag,
|
utils.AutoDAGFlag,
|
||||||
utils.TargetGasLimitFlag,
|
utils.TargetGasLimitFlag,
|
||||||
utils.NATFlag,
|
utils.NATFlag,
|
||||||
|
@ -149,12 +148,6 @@ participating.
|
||||||
utils.MetricsEnabledFlag,
|
utils.MetricsEnabledFlag,
|
||||||
utils.FakePoWFlag,
|
utils.FakePoWFlag,
|
||||||
utils.SolcPathFlag,
|
utils.SolcPathFlag,
|
||||||
utils.GpoMinGasPriceFlag,
|
|
||||||
utils.GpoMaxGasPriceFlag,
|
|
||||||
utils.GpoFullBlockRatioFlag,
|
|
||||||
utils.GpobaseStepDownFlag,
|
|
||||||
utils.GpobaseStepUpFlag,
|
|
||||||
utils.GpobaseCorrectionFactorFlag,
|
|
||||||
utils.ExtraDataFlag,
|
utils.ExtraDataFlag,
|
||||||
utils.VoteAccountFlag,
|
utils.VoteAccountFlag,
|
||||||
utils.VoteAccountPasswordFlag,
|
utils.VoteAccountPasswordFlag,
|
||||||
|
|
|
@ -134,17 +134,6 @@ var AppHelpFlagGroups = []flagGroup{
|
||||||
utils.NodeKeyHexFlag,
|
utils.NodeKeyHexFlag,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "GAS PRICE ORACLE",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
utils.GpoMinGasPriceFlag,
|
|
||||||
utils.GpoMaxGasPriceFlag,
|
|
||||||
utils.GpoFullBlockRatioFlag,
|
|
||||||
utils.GpobaseStepDownFlag,
|
|
||||||
utils.GpobaseStepUpFlag,
|
|
||||||
utils.GpobaseCorrectionFactorFlag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Name: "VIRTUAL MACHINE",
|
Name: "VIRTUAL MACHINE",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
|
|
|
@ -169,11 +169,6 @@ var (
|
||||||
Usage: "Public address for block mining rewards (default = first account created)",
|
Usage: "Public address for block mining rewards (default = first account created)",
|
||||||
Value: "0",
|
Value: "0",
|
||||||
}
|
}
|
||||||
GasPriceFlag = cli.StringFlag{
|
|
||||||
Name: "gasprice",
|
|
||||||
Usage: "Minimal gas price to accept for mining a transactions",
|
|
||||||
Value: common.Big0.String(),
|
|
||||||
}
|
|
||||||
ExtraDataFlag = cli.StringFlag{
|
ExtraDataFlag = cli.StringFlag{
|
||||||
Name: "extradata",
|
Name: "extradata",
|
||||||
Usage: "Block extra data set by the miner (default = client version)",
|
Usage: "Block extra data set by the miner (default = client version)",
|
||||||
|
@ -339,38 +334,6 @@ var (
|
||||||
Usage: "Solidity compiler command to be used",
|
Usage: "Solidity compiler command to be used",
|
||||||
Value: "solc",
|
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
|
// Quorum flags
|
||||||
VoteAccountFlag = cli.StringFlag{
|
VoteAccountFlag = cli.StringFlag{
|
||||||
Name: "voteaccount",
|
Name: "voteaccount",
|
||||||
|
@ -699,13 +662,6 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
|
||||||
DocRoot: ctx.GlobalString(DocRootFlag.Name),
|
DocRoot: ctx.GlobalString(DocRootFlag.Name),
|
||||||
EnableJit: jitEnabled,
|
EnableJit: jitEnabled,
|
||||||
ForceJit: ctx.GlobalBool(VMForceJitFlag.Name),
|
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),
|
SolcPath: ctx.GlobalString(SolcPathFlag.Name),
|
||||||
VoteMinBlockTime: uint(ctx.GlobalInt(VoteMinBlockTimeFlag.Name)),
|
VoteMinBlockTime: uint(ctx.GlobalInt(VoteMinBlockTimeFlag.Name)),
|
||||||
VoteMaxBlockTime: uint(ctx.GlobalInt(VoteMaxBlockTimeFlag.Name)),
|
VoteMaxBlockTime: uint(ctx.GlobalInt(VoteMaxBlockTimeFlag.Name)),
|
||||||
|
@ -728,9 +684,6 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
|
||||||
|
|
||||||
case ctx.GlobalBool(DevModeFlag.Name):
|
case ctx.GlobalBool(DevModeFlag.Name):
|
||||||
ethConf.Genesis = core.OlympicGenesisBlock()
|
ethConf.Genesis = core.OlympicGenesisBlock()
|
||||||
if !ctx.GlobalIsSet(GasPriceFlag.Name) {
|
|
||||||
ethConf.GasPrice = new(big.Int)
|
|
||||||
}
|
|
||||||
ethConf.PowTest = true
|
ethConf.PowTest = true
|
||||||
}
|
}
|
||||||
// Override any global options pertaining to the Ethereum protocol
|
// Override any global options pertaining to the Ethereum protocol
|
||||||
|
|
|
@ -223,7 +223,6 @@ func (be *registryAPIBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasSt
|
||||||
to = common.HexToAddress(toStr)
|
to = common.HexToAddress(toStr)
|
||||||
value = common.Big(valueStr)
|
value = common.Big(valueStr)
|
||||||
gas *big.Int
|
gas *big.Int
|
||||||
price *big.Int
|
|
||||||
data []byte
|
data []byte
|
||||||
contractCreation bool
|
contractCreation bool
|
||||||
)
|
)
|
||||||
|
@ -234,12 +233,6 @@ func (be *registryAPIBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasSt
|
||||||
gas = common.Big(gasStr)
|
gas = common.Big(gasStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(gasPriceStr) == 0 {
|
|
||||||
price = big.NewInt(10000000000000)
|
|
||||||
} else {
|
|
||||||
price = common.Big(gasPriceStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
data = common.FromHex(codeStr)
|
data = common.FromHex(codeStr)
|
||||||
if len(toStr) == 0 {
|
if len(toStr) == 0 {
|
||||||
contractCreation = true
|
contractCreation = true
|
||||||
|
@ -252,9 +245,9 @@ func (be *registryAPIBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasSt
|
||||||
|
|
||||||
var tx *types.Transaction
|
var tx *types.Transaction
|
||||||
if contractCreation {
|
if contractCreation {
|
||||||
tx = types.NewContractCreation(nonce, value, gas, price, data)
|
tx = types.NewContractCreation(nonce, value, gas, nil, data)
|
||||||
} else {
|
} 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())
|
signature, err := be.am.SignEthereum(from, tx.SigHash().Bytes())
|
||||||
|
|
|
@ -3,8 +3,6 @@ package quorum
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
@ -64,7 +62,6 @@ func (ps *pendingState) applyTransactions(txs *types.TransactionsByPriorityAndNo
|
||||||
var (
|
var (
|
||||||
lowGasTxs types.Transactions
|
lowGasTxs types.Transactions
|
||||||
failedTxs types.Transactions
|
failedTxs types.Transactions
|
||||||
gasPrice = new(big.Int).Mul(big.NewInt(20), common.Shannon)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var coalescedLogs vm.Logs
|
var coalescedLogs vm.Logs
|
||||||
|
@ -78,14 +75,6 @@ func (ps *pendingState) applyTransactions(txs *types.TransactionsByPriorityAndNo
|
||||||
// during transaction acceptance is the transaction pool.
|
// during transaction acceptance is the transaction pool.
|
||||||
from, _ := tx.From()
|
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
|
// Start executing the transaction
|
||||||
ps.state.StartRecord(tx.Hash(), common.Hash{}, 0)
|
ps.state.StartRecord(tx.Hash(), common.Hash{}, 0)
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,6 @@ func NewBlockVoting(bc *core.BlockChain, chainConfig *core.ChainConfig, txpool *
|
||||||
db: db,
|
db: db,
|
||||||
am: accountMgr,
|
am: accountMgr,
|
||||||
synced: isSynchronised,
|
synced: isSynchronised,
|
||||||
gasPrice: new(big.Int).Mul(big.NewInt(10), common.Shannon),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return bv
|
return bv
|
||||||
|
|
|
@ -19,6 +19,7 @@ package core
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
@ -87,6 +88,11 @@ func ApplyTransaction(config *ChainConfig, bc *BlockChain, gp *GasPool, publicSt
|
||||||
if !tx.IsPrivate() {
|
if !tx.IsPrivate() {
|
||||||
privateState = publicState
|
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)
|
_, gas, err := ApplyMessage(NewEnv(publicState, privateState, config, bc, tx, header, cfg), tx, gp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
|
|
|
@ -33,7 +33,7 @@ func TestStrictTxListAdd(t *testing.T) {
|
||||||
|
|
||||||
txs := make(types.Transactions, 1024)
|
txs := make(types.Transactions, 1024)
|
||||||
for i := 0; i < len(txs); i++ {
|
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
|
// Insert the transactions in a random order
|
||||||
list := newTxList(true)
|
list := newTxList(true)
|
||||||
|
|
|
@ -37,13 +37,12 @@ var (
|
||||||
// Transaction Pool Errors
|
// Transaction Pool Errors
|
||||||
ErrInvalidSender = errors.New("Invalid sender")
|
ErrInvalidSender = errors.New("Invalid sender")
|
||||||
ErrNonce = errors.New("Nonce too low")
|
ErrNonce = errors.New("Nonce too low")
|
||||||
ErrCheap = errors.New("Gas price too low for acceptance")
|
ErrInvalidGasPrice = errors.New("Gas price not 0")
|
||||||
ErrBalance = errors.New("Insufficient balance")
|
|
||||||
ErrNonExistentAccount = errors.New("Account does not exist or account balance too low")
|
|
||||||
ErrInsufficientFunds = errors.New("Insufficient funds for gas * price + value")
|
ErrInsufficientFunds = errors.New("Insufficient funds for gas * price + value")
|
||||||
ErrIntrinsicGas = errors.New("Intrinsic gas too low")
|
ErrIntrinsicGas = errors.New("Intrinsic gas too low")
|
||||||
ErrGasLimit = errors.New("Exceeds block gas limit")
|
ErrGasLimit = errors.New("Exceeds block gas limit")
|
||||||
ErrNegativeValue = errors.New("Negative value")
|
ErrNegativeValue = errors.New("Negative value")
|
||||||
|
ErrNonExistentAccount = errors.New("Account doesn't exist")
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -69,7 +68,6 @@ type TxPool struct {
|
||||||
currentState stateFn // The state function which will allow us to do some pre checks
|
currentState stateFn // The state function which will allow us to do some pre checks
|
||||||
pendingState *state.ManagedState
|
pendingState *state.ManagedState
|
||||||
gasLimit func() *big.Int // The current gas limit function callback
|
gasLimit func() *big.Int // The current gas limit function callback
|
||||||
minGasPrice *big.Int
|
|
||||||
eventMux *event.TypeMux
|
eventMux *event.TypeMux
|
||||||
events event.Subscription
|
events event.Subscription
|
||||||
localTx *txSet
|
localTx *txSet
|
||||||
|
@ -96,10 +94,9 @@ func NewTxPool(config *ChainConfig, eventMux *event.TypeMux, currentStateFn stat
|
||||||
eventMux: eventMux,
|
eventMux: eventMux,
|
||||||
currentState: currentStateFn,
|
currentState: currentStateFn,
|
||||||
gasLimit: gasLimitFn,
|
gasLimit: gasLimitFn,
|
||||||
minGasPrice: new(big.Int),
|
|
||||||
pendingState: nil,
|
pendingState: nil,
|
||||||
localTx: newTxSet(),
|
localTx: newTxSet(),
|
||||||
events: eventMux.Subscribe(ChainHeadEvent{}, GasPriceChanged{}, RemovedTransactionEvent{}),
|
events: eventMux.Subscribe(ChainHeadEvent{}, RemovedTransactionEvent{}),
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,10 +123,6 @@ func (pool *TxPool) eventLoop() {
|
||||||
|
|
||||||
pool.resetState()
|
pool.resetState()
|
||||||
pool.mu.Unlock()
|
pool.mu.Unlock()
|
||||||
case GasPriceChanged:
|
|
||||||
pool.mu.Lock()
|
|
||||||
pool.minGasPrice = ev.Price
|
|
||||||
pool.mu.Unlock()
|
|
||||||
case RemovedTransactionEvent:
|
case RemovedTransactionEvent:
|
||||||
pool.AddBatch(ev.Txs)
|
pool.AddBatch(ev.Txs)
|
||||||
}
|
}
|
||||||
|
@ -151,8 +144,7 @@ func (pool *TxPool) resetState() {
|
||||||
|
|
||||||
// validate the pool of pending transactions, this will remove
|
// validate the pool of pending transactions, this will remove
|
||||||
// any transactions that have been included in the block or
|
// any transactions that have been included in the block or
|
||||||
// have been invalidated because of another transaction (e.g.
|
// have been invalidated because of another transaction.
|
||||||
// higher gas price)
|
|
||||||
pool.demoteUnexecutables()
|
pool.demoteUnexecutables()
|
||||||
|
|
||||||
// Update all accounts to the latest known pending nonce
|
// Update all accounts to the latest known pending nonce
|
||||||
|
@ -231,8 +223,7 @@ func (pool *TxPool) Pending() map[common.Address]types.Transactions {
|
||||||
return pending
|
return pending
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLocal marks a transaction as local, skipping gas price
|
// SetLocal marks a transaction as local.
|
||||||
// check against local miner minimum in the future
|
|
||||||
func (pool *TxPool) SetLocal(tx *types.Transaction) {
|
func (pool *TxPool) SetLocal(tx *types.Transaction) {
|
||||||
pool.mu.Lock()
|
pool.mu.Lock()
|
||||||
defer pool.mu.Unlock()
|
defer pool.mu.Unlock()
|
||||||
|
@ -242,10 +233,10 @@ func (pool *TxPool) SetLocal(tx *types.Transaction) {
|
||||||
// validateTx checks whether a transaction is valid according
|
// validateTx checks whether a transaction is valid according
|
||||||
// to the consensus rules.
|
// to the consensus rules.
|
||||||
func (pool *TxPool) validateTx(tx *types.Transaction) error {
|
func (pool *TxPool) validateTx(tx *types.Transaction) error {
|
||||||
local := pool.localTx.contains(tx.Hash())
|
// due to dual state balances of private accounts cannot be determined.
|
||||||
// Drop transactions under our own minimal accepted gas price
|
// only accept transactions with a gas price of 0
|
||||||
if !local && pool.minGasPrice.Cmp(tx.GasPrice()) > 0 {
|
if tx.GasPrice().Cmp(common.Big0) != 0 {
|
||||||
return ErrCheap
|
return ErrInvalidGasPrice
|
||||||
}
|
}
|
||||||
|
|
||||||
currentState, _, err := pool.currentState()
|
currentState, _, err := pool.currentState()
|
||||||
|
|
|
@ -31,8 +31,8 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
)
|
)
|
||||||
|
|
||||||
func transaction(nonce uint64, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
|
func transaction(nonce uint64, gasPrice, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
|
||||||
tx, _ := types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, big.NewInt(1), nil).SignECDSA(key)
|
tx, _ := types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, gasPrice, nil).SignECDSA(key)
|
||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,11 +50,7 @@ func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
|
||||||
func TestInvalidTransactions(t *testing.T) {
|
func TestInvalidTransactions(t *testing.T) {
|
||||||
pool, key := setupTxPool()
|
pool, key := setupTxPool()
|
||||||
|
|
||||||
tx := transaction(0, big.NewInt(100), key)
|
tx := transaction(0, big.NewInt(0), big.NewInt(100), key)
|
||||||
if err := pool.Add(tx); err != ErrNonExistentAccount {
|
|
||||||
t.Error("expected", ErrNonExistentAccount)
|
|
||||||
}
|
|
||||||
|
|
||||||
from, _ := tx.From()
|
from, _ := tx.From()
|
||||||
currentState, _, _ := pool.currentState()
|
currentState, _, _ := pool.currentState()
|
||||||
currentState.AddBalance(from, big.NewInt(1))
|
currentState.AddBalance(from, big.NewInt(1))
|
||||||
|
@ -70,26 +66,15 @@ func TestInvalidTransactions(t *testing.T) {
|
||||||
|
|
||||||
currentState.SetNonce(from, 1)
|
currentState.SetNonce(from, 1)
|
||||||
currentState.AddBalance(from, big.NewInt(0xffffffffffffff))
|
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 {
|
if err := pool.Add(tx); err != ErrNonce {
|
||||||
t.Error("expected", ErrNonce)
|
t.Error("expected", ErrNonce, "got", err)
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransactionQueue(t *testing.T) {
|
func TestTransactionQueue(t *testing.T) {
|
||||||
pool, key := setupTxPool()
|
pool, key := setupTxPool()
|
||||||
tx := transaction(0, big.NewInt(100), key)
|
tx := transaction(0, big.NewInt(0), big.NewInt(100), key)
|
||||||
from, _ := tx.From()
|
from, _ := tx.From()
|
||||||
currentState, _, _ := pool.currentState()
|
currentState, _, _ := pool.currentState()
|
||||||
currentState.AddBalance(from, big.NewInt(1000))
|
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))
|
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()
|
from, _ = tx.From()
|
||||||
currentState.SetNonce(from, 2)
|
currentState.SetNonce(from, 2)
|
||||||
pool.enqueueTx(tx.Hash(), tx)
|
pool.enqueueTx(tx.Hash(), tx)
|
||||||
|
@ -114,9 +99,9 @@ func TestTransactionQueue(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pool, key = setupTxPool()
|
pool, key = setupTxPool()
|
||||||
tx1 := transaction(0, big.NewInt(100), key)
|
tx1 := transaction(0, big.NewInt(0), big.NewInt(100), key)
|
||||||
tx2 := transaction(10, big.NewInt(100), key)
|
tx2 := transaction(10, big.NewInt(0), big.NewInt(100), key)
|
||||||
tx3 := transaction(11, big.NewInt(100), key)
|
tx3 := transaction(11, big.NewInt(0), big.NewInt(100), key)
|
||||||
from, _ = tx1.From()
|
from, _ = tx1.From()
|
||||||
currentState, _, _ = pool.currentState()
|
currentState, _, _ = pool.currentState()
|
||||||
currentState.AddBalance(from, big.NewInt(1000))
|
currentState.AddBalance(from, big.NewInt(1000))
|
||||||
|
@ -136,7 +121,7 @@ func TestTransactionQueue(t *testing.T) {
|
||||||
|
|
||||||
func TestRemoveTx(t *testing.T) {
|
func TestRemoveTx(t *testing.T) {
|
||||||
pool, key := setupTxPool()
|
pool, key := setupTxPool()
|
||||||
tx := transaction(0, big.NewInt(100), key)
|
tx := transaction(0, big.NewInt(0), big.NewInt(100), key)
|
||||||
from, _ := tx.From()
|
from, _ := tx.From()
|
||||||
currentState, _, _ := pool.currentState()
|
currentState, _, _ := pool.currentState()
|
||||||
currentState.AddBalance(from, big.NewInt(1))
|
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) {
|
func TestTransactionChainFork(t *testing.T) {
|
||||||
pool, key := setupTxPool()
|
pool, key := setupTxPool()
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
@ -183,7 +156,7 @@ func TestTransactionChainFork(t *testing.T) {
|
||||||
}
|
}
|
||||||
resetState()
|
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 {
|
if err := pool.add(tx); err != nil {
|
||||||
t.Error("didn't expect error", err)
|
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) {
|
func TestMissingNonce(t *testing.T) {
|
||||||
pool, key := setupTxPool()
|
pool, key := setupTxPool()
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
currentState, _, _ := pool.currentState()
|
currentState, _, _ := pool.currentState()
|
||||||
currentState.AddBalance(addr, big.NewInt(100000000000000))
|
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 {
|
if err := pool.add(tx); err != nil {
|
||||||
t.Error("didn't expect error", err)
|
t.Error("didn't expect error", err)
|
||||||
}
|
}
|
||||||
|
@ -272,7 +197,7 @@ func TestNonceRecovery(t *testing.T) {
|
||||||
currentState.SetNonce(addr, n)
|
currentState.SetNonce(addr, n)
|
||||||
currentState.AddBalance(addr, big.NewInt(100000000000000))
|
currentState.AddBalance(addr, big.NewInt(100000000000000))
|
||||||
pool.resetState()
|
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 {
|
if err := pool.Add(tx); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -286,7 +211,7 @@ func TestNonceRecovery(t *testing.T) {
|
||||||
|
|
||||||
func TestRemovedTxEvent(t *testing.T) {
|
func TestRemovedTxEvent(t *testing.T) {
|
||||||
pool, key := setupTxPool()
|
pool, key := setupTxPool()
|
||||||
tx := transaction(0, big.NewInt(1000000), key)
|
tx := transaction(0, big.NewInt(0), big.NewInt(1000000), key)
|
||||||
from, _ := tx.From()
|
from, _ := tx.From()
|
||||||
currentState, _, _ := pool.currentState()
|
currentState, _, _ := pool.currentState()
|
||||||
currentState.AddBalance(from, big.NewInt(1000000000000))
|
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
|
// Tests that if the transaction count belonging to a single account goes above
|
||||||
// some threshold, the higher transactions are dropped to prevent DOS attacks.
|
// some threshold, the higher transactions are dropped to prevent DOS attacks.
|
||||||
func TestTransactionQueueAccountLimiting(t *testing.T) {
|
func TestTransactionQueueAccountLimiting(t *testing.T) {
|
||||||
// Create a test account and fund it
|
// Create a test account and fund it
|
||||||
pool, key := setupTxPool()
|
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, _, _ := pool.currentState()
|
||||||
state.AddBalance(account, big.NewInt(1000000))
|
state.AddBalance(account, big.NewInt(1000000))
|
||||||
|
|
||||||
// Keep queuing up transactions and make sure all above a limit are dropped
|
// Keep queuing up transactions and make sure all above a limit are dropped
|
||||||
for i := uint64(1); i <= maxQueuedPerAccount+5; i++ {
|
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)
|
t.Fatalf("tx %d: failed to add transaction: %v", i, err)
|
||||||
}
|
}
|
||||||
if len(pool.pending) != 0 {
|
if len(pool.pending) != 0 {
|
||||||
|
@ -501,7 +288,7 @@ func TestTransactionQueueGlobalLimiting(t *testing.T) {
|
||||||
key := keys[rand.Intn(len(keys))]
|
key := keys[rand.Intn(len(keys))]
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
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]++
|
nonces[addr]++
|
||||||
}
|
}
|
||||||
// Import the batch and verify that limits have been enforced
|
// 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
|
// Create a test account and fund it
|
||||||
pool, key := setupTxPool()
|
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, _, _ := pool.currentState()
|
||||||
state.AddBalance(account, big.NewInt(1000000))
|
state.AddBalance(account, big.NewInt(1000000))
|
||||||
|
|
||||||
// Queue up a batch of transactions
|
// Queue up a batch of transactions
|
||||||
for i := uint64(1); i <= maxQueuedPerAccount; i++ {
|
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)
|
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) {
|
func TestTransactionPendingLimiting(t *testing.T) {
|
||||||
// Create a test account and fund it
|
// Create a test account and fund it
|
||||||
pool, key := setupTxPool()
|
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, _, _ := pool.currentState()
|
||||||
state.AddBalance(account, big.NewInt(1000000))
|
state.AddBalance(account, big.NewInt(1000000))
|
||||||
|
|
||||||
// Keep queuing up transactions and make sure all above a limit are dropped
|
// Keep queuing up transactions and make sure all above a limit are dropped
|
||||||
for i := uint64(0); i < maxQueuedPerAccount+5; i++ {
|
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)
|
t.Fatalf("tx %d: failed to add transaction: %v", i, err)
|
||||||
}
|
}
|
||||||
if pool.pending[account].Len() != int(i)+1 {
|
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) {
|
func testTransactionLimitingEquivalency(t *testing.T, origin uint64) {
|
||||||
// Add a batch of transactions to a pool one by one
|
// Add a batch of transactions to a pool one by one
|
||||||
pool1, key1 := setupTxPool()
|
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, _, _ := pool1.currentState()
|
||||||
state1.AddBalance(account1, big.NewInt(1000000))
|
state1.AddBalance(account1, big.NewInt(1000000))
|
||||||
|
|
||||||
for i := uint64(0); i < maxQueuedPerAccount+5; i++ {
|
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)
|
t.Fatalf("tx %d: failed to add transaction: %v", i, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Add a batch of transactions to a pool in one big batch
|
// Add a batch of transactions to a pool in one big batch
|
||||||
pool2, key2 := setupTxPool()
|
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, _, _ := pool2.currentState()
|
||||||
state2.AddBalance(account2, big.NewInt(1000000))
|
state2.AddBalance(account2, big.NewInt(1000000))
|
||||||
|
|
||||||
txns := []*types.Transaction{}
|
txns := []*types.Transaction{}
|
||||||
for i := uint64(0); i < maxQueuedPerAccount+5; i++ {
|
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)
|
pool2.AddBatch(txns)
|
||||||
|
|
||||||
|
@ -648,7 +435,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) {
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
for j := 0; j < int(maxPendingTotal)/len(keys)*2; j++ {
|
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]++
|
nonces[addr]++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -694,7 +481,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) {
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
for j := 0; j < int(minPendingPerAccount)*2; j++ {
|
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]++
|
nonces[addr]++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -717,12 +504,12 @@ func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 1
|
||||||
func benchmarkPendingDemotion(b *testing.B, size int) {
|
func benchmarkPendingDemotion(b *testing.B, size int) {
|
||||||
// Add a batch of transactions to a pool one by one
|
// Add a batch of transactions to a pool one by one
|
||||||
pool, key := setupTxPool()
|
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, _, _ := pool.currentState()
|
||||||
state.AddBalance(account, big.NewInt(1000000))
|
state.AddBalance(account, big.NewInt(1000000))
|
||||||
|
|
||||||
for i := 0; i < size; i++ {
|
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)
|
pool.promoteTx(account, tx.Hash(), tx)
|
||||||
}
|
}
|
||||||
// Benchmark the speed of pool validation
|
// 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) {
|
func benchmarkFuturePromotion(b *testing.B, size int) {
|
||||||
// Add a batch of transactions to a pool one by one
|
// Add a batch of transactions to a pool one by one
|
||||||
pool, key := setupTxPool()
|
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, _, _ := pool.currentState()
|
||||||
state.AddBalance(account, big.NewInt(1000000))
|
state.AddBalance(account, big.NewInt(1000000))
|
||||||
|
|
||||||
for i := 0; i < size; i++ {
|
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)
|
pool.enqueueTx(tx.Hash(), tx)
|
||||||
}
|
}
|
||||||
// Benchmark the speed of pool validation
|
// Benchmark the speed of pool validation
|
||||||
|
@ -760,13 +547,13 @@ func benchmarkFuturePromotion(b *testing.B, size int) {
|
||||||
func BenchmarkPoolInsert(b *testing.B) {
|
func BenchmarkPoolInsert(b *testing.B) {
|
||||||
// Generate a batch of transactions to enqueue into the pool
|
// Generate a batch of transactions to enqueue into the pool
|
||||||
pool, key := setupTxPool()
|
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, _, _ := pool.currentState()
|
||||||
state.AddBalance(account, big.NewInt(1000000))
|
state.AddBalance(account, big.NewInt(1000000))
|
||||||
|
|
||||||
txs := make(types.Transactions, b.N)
|
txs := make(types.Transactions, b.N)
|
||||||
for i := 0; i < b.N; i++ {
|
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
|
// Benchmark importing the transactions into the queue
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
@ -783,7 +570,7 @@ func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 1
|
||||||
func benchmarkPoolBatchInsert(b *testing.B, size int) {
|
func benchmarkPoolBatchInsert(b *testing.B, size int) {
|
||||||
// Generate a batch of transactions to enqueue into the pool
|
// Generate a batch of transactions to enqueue into the pool
|
||||||
pool, key := setupTxPool()
|
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, _, _ := pool.currentState()
|
||||||
state.AddBalance(account, big.NewInt(1000000))
|
state.AddBalance(account, big.NewInt(1000000))
|
||||||
|
|
||||||
|
@ -791,7 +578,7 @@ func benchmarkPoolBatchInsert(b *testing.B, size int) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
batches[i] = make(types.Transactions, size)
|
batches[i] = make(types.Transactions, size)
|
||||||
for j := 0; j < size; j++ {
|
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
|
// Benchmark importing the transactions into the queue
|
||||||
|
|
|
@ -26,9 +26,8 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// from bcValidBlockTest.json, "SimpleTx"
|
|
||||||
func TestBlockEncoding(t *testing.T) {
|
func TestBlockEncoding(t *testing.T) {
|
||||||
blockEnc := common.FromHex("f90260f901f9a083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f861f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1c0")
|
blockEnc := common.FromHex("f90260f901f9a083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a08bba9707f73a6c9801825706d0814d4ae310e4ff0a16fcd94e72174a176930e4a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f861f85f808082c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1c0")
|
||||||
var block Block
|
var block Block
|
||||||
if err := rlp.DecodeBytes(blockEnc, &block); err != nil {
|
if err := rlp.DecodeBytes(blockEnc, &block); err != nil {
|
||||||
t.Fatal("decode error: ", err)
|
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)
|
t.Errorf("%s mismatch: got %v, want %v", f, got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
check("Difficulty", block.Difficulty(), big.NewInt(131072))
|
check("Difficulty", block.Difficulty(), big.NewInt(131072))
|
||||||
check("GasLimit", block.GasLimit(), big.NewInt(3141592))
|
check("GasLimit", block.GasLimit(), big.NewInt(3141592))
|
||||||
check("GasUsed", block.GasUsed(), big.NewInt(21000))
|
check("GasUsed", block.GasUsed(), big.NewInt(21000))
|
||||||
check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1"))
|
check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1"))
|
||||||
check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498"))
|
check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498"))
|
||||||
check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017"))
|
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("Nonce", block.Nonce(), uint64(0xa13a5a8c8f2bb1c4))
|
||||||
check("Time", block.Time(), big.NewInt(1426516743))
|
check("Time", block.Time(), big.NewInt(1426516743))
|
||||||
check("Size", block.Size(), common.StorageSize(len(blockEnc)))
|
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"))
|
tx1, _ = tx1.WithSignature(common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b11b"))
|
||||||
check("len(Transactions)", len(block.Transactions()), 1)
|
check("len(Transactions)", len(block.Transactions()), 1)
|
||||||
check("Transactions[0].Hash", block.Transactions()[0].Hash(), tx1.Hash())
|
check("Transactions[0].Hash", block.Transactions()[0].Hash(), tx1.Hash())
|
||||||
|
|
|
@ -80,7 +80,7 @@ func NewContractCreation(nonce uint64, amount, gasLimit, gasPrice *big.Int, data
|
||||||
Recipient: nil,
|
Recipient: nil,
|
||||||
Amount: new(big.Int).Set(amount),
|
Amount: new(big.Int).Set(amount),
|
||||||
GasLimit: new(big.Int).Set(gasLimit),
|
GasLimit: new(big.Int).Set(gasLimit),
|
||||||
Price: new(big.Int).Set(gasPrice),
|
Price: new(big.Int),
|
||||||
Payload: data,
|
Payload: data,
|
||||||
R: new(big.Int),
|
R: new(big.Int),
|
||||||
S: new(big.Int),
|
S: new(big.Int),
|
||||||
|
@ -108,9 +108,6 @@ func NewTransaction(nonce uint64, to common.Address, amount, gasLimit, gasPrice
|
||||||
if gasLimit != nil {
|
if gasLimit != nil {
|
||||||
d.GasLimit.Set(gasLimit)
|
d.GasLimit.Set(gasLimit)
|
||||||
}
|
}
|
||||||
if gasPrice != nil {
|
|
||||||
d.Price.Set(gasPrice)
|
|
||||||
}
|
|
||||||
return &Transaction{data: d}
|
return &Transaction{data: d}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ var (
|
||||||
common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"),
|
common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"),
|
||||||
big.NewInt(10),
|
big.NewInt(10),
|
||||||
big.NewInt(2000),
|
big.NewInt(2000),
|
||||||
big.NewInt(1),
|
big.NewInt(0),
|
||||||
common.FromHex("5544"),
|
common.FromHex("5544"),
|
||||||
).WithSignature(
|
).WithSignature(
|
||||||
common.Hex2Bytes("98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a31c"),
|
common.Hex2Bytes("98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a31c"),
|
||||||
|
@ -56,8 +56,8 @@ func TestTransactionSigHash(t *testing.T) {
|
||||||
if emptyTx.SigHash() != common.HexToHash("c775b99e7ad12f50d819fcd602390467e28141316969f4b57f0626f74fe3b386") {
|
if emptyTx.SigHash() != common.HexToHash("c775b99e7ad12f50d819fcd602390467e28141316969f4b57f0626f74fe3b386") {
|
||||||
t.Errorf("empty transaction hash mismatch, got %x", emptyTx.Hash())
|
t.Errorf("empty transaction hash mismatch, got %x", emptyTx.Hash())
|
||||||
}
|
}
|
||||||
if rightvrsTx.SigHash() != common.HexToHash("fe7a79529ed5f7c3375d06b26b186a8644e0e16c373d7a12be41c62d6042b77a") {
|
if rightvrsTx.SigHash() != common.HexToHash("c75e06c2a1b4e254e869653871436fdfa752fd613152b474e6dd36b73a13dae2") {
|
||||||
t.Errorf("RightVRS transaction hash mismatch, got %x", rightvrsTx.Hash())
|
t.Errorf("RightVRS transaction hash mismatch, got %x", rightvrsTx.SigHash())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ func TestTransactionEncode(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("encode error: %v", err)
|
t.Fatalf("encode error: %v", err)
|
||||||
}
|
}
|
||||||
should := common.FromHex("f86103018207d094b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a8255441ca098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa08887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3")
|
should := common.FromHex("f86103808207d094b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a8255441ca098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa08887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3")
|
||||||
if !bytes.Equal(txb, should) {
|
if !bytes.Equal(txb, should) {
|
||||||
t.Errorf("encoded RLP mismatch, got %x", txb)
|
t.Errorf("encoded RLP mismatch, got %x", txb)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
"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/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
|
@ -37,7 +36,6 @@ import (
|
||||||
// EthApiBackend implements ethapi.Backend for full nodes
|
// EthApiBackend implements ethapi.Backend for full nodes
|
||||||
type EthApiBackend struct {
|
type EthApiBackend struct {
|
||||||
eth *Ethereum
|
eth *Ethereum
|
||||||
gpo *gasprice.GasPriceOracle
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthApiBackend) SetHead(number uint64) {
|
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) {
|
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 {
|
func (b *EthApiBackend) ChainDb() ethdb.Database {
|
||||||
|
|
|
@ -20,7 +20,6 @@ package eth
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -39,7 +38,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||||
"github.com/ethereum/go-ethereum/eth/filters"
|
"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/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
|
@ -82,17 +80,9 @@ type Config struct {
|
||||||
ExtraData []byte
|
ExtraData []byte
|
||||||
|
|
||||||
Etherbase common.Address
|
Etherbase common.Address
|
||||||
GasPrice *big.Int
|
|
||||||
MinerThreads int
|
MinerThreads int
|
||||||
SolcPath string
|
SolcPath string
|
||||||
|
|
||||||
GpoMinGasPrice *big.Int
|
|
||||||
GpoMaxGasPrice *big.Int
|
|
||||||
GpoFullBlockRatio int
|
|
||||||
GpobaseStepDown int
|
|
||||||
GpobaseStepUp int
|
|
||||||
GpobaseCorrectionFactor int
|
|
||||||
|
|
||||||
EnableJit bool
|
EnableJit bool
|
||||||
ForceJit bool
|
ForceJit bool
|
||||||
|
|
||||||
|
@ -227,16 +217,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
gpoParams := &gasprice.GpoParams{
|
eth.apiBackend = &EthApiBackend{eth}
|
||||||
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.blockVoting = quorum.NewBlockVoting(eth.blockchain, eth.chainConfig, eth.txPool, eth.eventMux, eth.chainDb, eth.accountManager, config.SingleBlockMaker)
|
eth.blockVoting = quorum.NewBlockVoting(eth.blockchain, eth.chainConfig, eth.txPool, eth.eventMux, eth.chainDb, eth.accountManager, config.SingleBlockMaker)
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -283,9 +283,9 @@ func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if args.To == nil {
|
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 {
|
} 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())
|
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)
|
msg.gas = big.NewInt(50000000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if msg.gasPrice.Cmp(common.Big0) != 0 {
|
||||||
|
msg.gasPrice = new(big.Int)
|
||||||
|
}
|
||||||
|
|
||||||
// Execute the call and return
|
// Execute the call and return
|
||||||
vmenv, vmError, err := s.b.GetVMEnv(ctx, msg, state, header)
|
vmenv, vmError, err := s.b.GetVMEnv(ctx, msg, state, header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1086,9 +1090,9 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if args.To == nil {
|
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 {
|
} 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())
|
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 {
|
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 {
|
} 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
|
return nil
|
||||||
|
@ -1263,9 +1267,9 @@ func (s *PublicTransactionPoolAPI) SignTransaction(ctx context.Context, args Sig
|
||||||
|
|
||||||
var tx *types.Transaction
|
var tx *types.Transaction
|
||||||
if args.To == nil {
|
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 {
|
} 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)
|
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
|
var newTx *types.Transaction
|
||||||
if tx.tx.To() == nil {
|
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 {
|
} 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() {
|
if tx.tx.IsPrivate() {
|
||||||
newTx.SetPrivate()
|
newTx.SetPrivate()
|
||||||
|
|
|
@ -22,34 +22,6 @@ import (
|
||||||
"testing"
|
"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) {
|
func TestBcInvalidHeaderTests(t *testing.T) {
|
||||||
err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
|
err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
|
||||||
if err != nil {
|
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) {
|
func TestBcTotalDifficulty(t *testing.T) {
|
||||||
// skip because these will fail due to selfish mining fix
|
// skip because these will fail due to selfish mining fix
|
||||||
t.Skip()
|
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
|
// TODO: iterate over files once we got more than a few
|
||||||
func TestBcRandom(t *testing.T) {
|
func TestBcRandom(t *testing.T) {
|
||||||
err := RunBlockTest(big.NewInt(1000000), nil, big.NewInt(10), filepath.Join(blockTestDir, "RandomTests/bl201507071825GO.json"), BlockSkipTests)
|
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) {
|
func TestHomesteadBcInvalidHeaderTests(t *testing.T) {
|
||||||
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcInvalidHeaderTest.json"), BlockSkipTests)
|
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcInvalidHeaderTest.json"), BlockSkipTests)
|
||||||
if err != nil {
|
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) {
|
func TestHomesteadBcSuicideIssue(t *testing.T) {
|
||||||
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcSuicideIssue.json"), BlockSkipTests)
|
err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcSuicideIssue.json"), BlockSkipTests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
{
|
{
|
||||||
"data" : "0x",
|
"data" : "0x",
|
||||||
"gasLimit" : "0x44aa20",
|
"gasLimit" : "0x44aa20",
|
||||||
"gasPrice" : "0x01",
|
"gasPrice" : "0x00",
|
||||||
"nonce" : "0x00",
|
"nonce" : "0x00",
|
||||||
"r" : "0x836bdd27c1abba1a55221bc86f6f048c9e364680eebf9f3ab9b6c7ae462b76ee",
|
"r" : "0x836bdd27c1abba1a55221bc86f6f048c9e364680eebf9f3ab9b6c7ae462b76ee",
|
||||||
"s" : "0x0c6fbd2f365de9e87436d2ac7635b709093038befc6ec9933ee936ab0b4a24b6",
|
"s" : "0x0c6fbd2f365de9e87436d2ac7635b709093038befc6ec9933ee936ab0b4a24b6",
|
||||||
|
|
Loading…
Reference in New Issue