mirror of https://github.com/poanetwork/quorum.git
Transaction size limit support via genesis
This commit is contained in:
parent
918aaa83a9
commit
cca2e84c18
|
@ -75,7 +75,6 @@ var (
|
||||||
utils.TxPoolNoLocalsFlag,
|
utils.TxPoolNoLocalsFlag,
|
||||||
utils.TxPoolJournalFlag,
|
utils.TxPoolJournalFlag,
|
||||||
utils.TxPoolRejournalFlag,
|
utils.TxPoolRejournalFlag,
|
||||||
utils.TxPoolSizeLimitFlag,
|
|
||||||
utils.TxPoolPriceLimitFlag,
|
utils.TxPoolPriceLimitFlag,
|
||||||
utils.TxPoolPriceBumpFlag,
|
utils.TxPoolPriceBumpFlag,
|
||||||
utils.TxPoolAccountSlotsFlag,
|
utils.TxPoolAccountSlotsFlag,
|
||||||
|
|
|
@ -117,7 +117,6 @@ var AppHelpFlagGroups = []flagGroup{
|
||||||
utils.TxPoolNoLocalsFlag,
|
utils.TxPoolNoLocalsFlag,
|
||||||
utils.TxPoolJournalFlag,
|
utils.TxPoolJournalFlag,
|
||||||
utils.TxPoolRejournalFlag,
|
utils.TxPoolRejournalFlag,
|
||||||
utils.TxPoolSizeLimitFlag,
|
|
||||||
utils.TxPoolPriceLimitFlag,
|
utils.TxPoolPriceLimitFlag,
|
||||||
utils.TxPoolPriceBumpFlag,
|
utils.TxPoolPriceBumpFlag,
|
||||||
utils.TxPoolAccountSlotsFlag,
|
utils.TxPoolAccountSlotsFlag,
|
||||||
|
|
|
@ -260,11 +260,6 @@ var (
|
||||||
Usage: "Time interval to regenerate the local transaction journal",
|
Usage: "Time interval to regenerate the local transaction journal",
|
||||||
Value: core.DefaultTxPoolConfig.Rejournal,
|
Value: core.DefaultTxPoolConfig.Rejournal,
|
||||||
}
|
}
|
||||||
TxPoolSizeLimitFlag = cli.Uint64Flag{
|
|
||||||
Name: "txsizelimit",
|
|
||||||
Usage: "Maximum size allowed for valid transaction (in KB)",
|
|
||||||
Value: 32,
|
|
||||||
}
|
|
||||||
TxPoolPriceLimitFlag = cli.Uint64Flag{
|
TxPoolPriceLimitFlag = cli.Uint64Flag{
|
||||||
Name: "txpool.pricelimit",
|
Name: "txpool.pricelimit",
|
||||||
Usage: "Minimum gas price limit to enforce for acceptance into the pool",
|
Usage: "Minimum gas price limit to enforce for acceptance into the pool",
|
||||||
|
@ -1010,9 +1005,6 @@ func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
|
||||||
if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) {
|
if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) {
|
||||||
cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name)
|
cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(TxPoolSizeLimitFlag.Name) {
|
|
||||||
cfg.SizeLimit = ctx.GlobalUint64(TxPoolSizeLimitFlag.Name)
|
|
||||||
}
|
|
||||||
if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) {
|
if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) {
|
||||||
cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name)
|
cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,6 +164,18 @@ func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig
|
||||||
} else {
|
} else {
|
||||||
log.Info("Writing custom genesis block")
|
log.Info("Writing custom genesis block")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set default transaction size limit if not set in genesis
|
||||||
|
if genesis.Config.SizeLimit == 0 {
|
||||||
|
genesis.Config.SizeLimit = DefaultTxPoolConfig.SizeLimit
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check transaction size limit
|
||||||
|
err := genesis.Config.IsValid()
|
||||||
|
if err != nil {
|
||||||
|
return genesis.Config, common.Hash{}, err
|
||||||
|
}
|
||||||
|
|
||||||
block, err := genesis.Commit(db)
|
block, err := genesis.Commit(db)
|
||||||
return genesis.Config, block.Hash(), err
|
return genesis.Config, block.Hash(), err
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
"errors"
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
@ -85,6 +86,15 @@ func TestSetupGenesis(t *testing.T) {
|
||||||
wantHash: params.MainnetGenesisHash,
|
wantHash: params.MainnetGenesisHash,
|
||||||
wantConfig: params.MainnetChainConfig,
|
wantConfig: params.MainnetChainConfig,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "genesis with incorrect SizeLimit",
|
||||||
|
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||||
|
customg.Config.SizeLimit = 100000
|
||||||
|
return SetupGenesisBlock(db, &customg)
|
||||||
|
},
|
||||||
|
wantErr: errors.New("Genesis transaction size limit must be between 32 and 128"),
|
||||||
|
wantConfig: customg.Config,
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// name: "custom block in DB, genesis == nil",
|
// name: "custom block in DB, genesis == nil",
|
||||||
// fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
// fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||||
|
|
|
@ -152,7 +152,7 @@ var DefaultTxPoolConfig = TxPoolConfig{
|
||||||
Journal: "transactions.rlp",
|
Journal: "transactions.rlp",
|
||||||
Rejournal: time.Hour,
|
Rejournal: time.Hour,
|
||||||
|
|
||||||
SizeLimit: 32,
|
SizeLimit: 64,
|
||||||
|
|
||||||
PriceLimit: 1,
|
PriceLimit: 1,
|
||||||
PriceBump: 10,
|
PriceBump: 10,
|
||||||
|
@ -173,10 +173,6 @@ func (config *TxPoolConfig) sanitize() TxPoolConfig {
|
||||||
log.Warn("Sanitizing invalid txpool journal time", "provided", conf.Rejournal, "updated", time.Second)
|
log.Warn("Sanitizing invalid txpool journal time", "provided", conf.Rejournal, "updated", time.Second)
|
||||||
conf.Rejournal = time.Second
|
conf.Rejournal = time.Second
|
||||||
}
|
}
|
||||||
if conf.SizeLimit < 32 || conf.SizeLimit > 128 {
|
|
||||||
log.Warn("Sanitizing invalid txpool size limit", "provided", conf.SizeLimit, "updated", DefaultTxPoolConfig.SizeLimit)
|
|
||||||
conf.SizeLimit = DefaultTxPoolConfig.SizeLimit
|
|
||||||
}
|
|
||||||
if conf.PriceLimit < 1 {
|
if conf.PriceLimit < 1 {
|
||||||
log.Warn("Sanitizing invalid txpool price limit", "provided", conf.PriceLimit, "updated", DefaultTxPoolConfig.PriceLimit)
|
log.Warn("Sanitizing invalid txpool price limit", "provided", conf.PriceLimit, "updated", DefaultTxPoolConfig.PriceLimit)
|
||||||
conf.PriceLimit = DefaultTxPoolConfig.PriceLimit
|
conf.PriceLimit = DefaultTxPoolConfig.PriceLimit
|
||||||
|
@ -568,12 +564,13 @@ func (pool *TxPool) local() map[common.Address]types.Transactions {
|
||||||
// rules and adheres to some heuristic limits of the local node (price and size).
|
// rules and adheres to some heuristic limits of the local node (price and size).
|
||||||
func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
|
func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
|
||||||
isQuorum := pool.chainconfig.IsQuorum
|
isQuorum := pool.chainconfig.IsQuorum
|
||||||
|
sizeLimit := pool.chainconfig.SizeLimit
|
||||||
|
|
||||||
if isQuorum && tx.GasPrice().Cmp(common.Big0) != 0 {
|
if isQuorum && tx.GasPrice().Cmp(common.Big0) != 0 {
|
||||||
return ErrInvalidGasPrice
|
return ErrInvalidGasPrice
|
||||||
}
|
}
|
||||||
// Reject transactions over 32KB (or manually set limit) to prevent DOS attacks
|
// Reject transactions over 32KB (or manually set limit) to prevent DOS attacks
|
||||||
if float64(tx.Size()) > float64(pool.config.SizeLimit*1024) {
|
if float64(tx.Size()) > float64(sizeLimit * 1024) {
|
||||||
return ErrOversizedData
|
return ErrOversizedData
|
||||||
}
|
}
|
||||||
// Transactions can't be negative. This may never happen using RLP decoded
|
// Transactions can't be negative. This may never happen using RLP decoded
|
||||||
|
|
|
@ -284,28 +284,28 @@ func TestInvalidTransactions(t *testing.T) {
|
||||||
t.Error("expected", ErrOversizedData, "; got", err)
|
t.Error("expected", ErrOversizedData, "; got", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
db, _ := ethdb.NewMemDatabase()
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
blockchain := &testBlockChain{statedb, statedb, 1000000, new(event.Feed)}
|
||||||
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
params.TestChainConfig.SizeLimit = 128
|
||||||
config := testTxPoolConfig
|
pool2 := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
|
||||||
config.SizeLimit = 128
|
|
||||||
pool2 := NewTxPool(config, params.TestChainConfig, blockchain)
|
|
||||||
pool2.currentState.AddBalance(from, big.NewInt(0xffffffffffffff))
|
pool2.currentState.AddBalance(from, big.NewInt(0xffffffffffffff))
|
||||||
data2 := make([]byte, (127 * 1024))
|
data2 := make([]byte, (127 * 1024))
|
||||||
|
|
||||||
tx3, _ := types.SignTx(types.NewTransaction(2, common.Address{}, big.NewInt(100), big.NewInt(100000), big.NewInt(1), data2), types.HomesteadSigner{}, key)
|
tx3, _ := types.SignTx(types.NewTransaction(2, common.Address{}, big.NewInt(100), 100000, big.NewInt(1), data2), types.HomesteadSigner{}, key)
|
||||||
if err := pool2.AddRemote(tx3); err != ErrIntrinsicGas {
|
if err := pool2.AddRemote(tx3); err != ErrIntrinsicGas {
|
||||||
t.Error("expected", ErrIntrinsicGas, "; got", err)
|
t.Error("expected", ErrIntrinsicGas, "; got", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
data3 := make([]byte, (128*1024)+1)
|
data3 := make([]byte, (128*1024)+1)
|
||||||
tx4, _ := types.SignTx(types.NewTransaction(2, common.Address{}, big.NewInt(100), big.NewInt(100000), big.NewInt(1), data3), types.HomesteadSigner{}, key)
|
tx4, _ := types.SignTx(types.NewTransaction(2, common.Address{}, big.NewInt(100), 100000, big.NewInt(1), data3), types.HomesteadSigner{}, key)
|
||||||
if err := pool2.AddRemote(tx4); err != ErrOversizedData {
|
if err := pool2.AddRemote(tx4); err != ErrOversizedData {
|
||||||
t.Error("expected", ErrOversizedData, "; got", err)
|
t.Error("expected", ErrOversizedData, "; got", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tx5, _ := types.SignTx(types.NewTransaction(1, common.Address{}, big.NewInt(100), common.Big0, big.NewInt(0), nil), types.HomesteadSigner{}, key)
|
tx5, _ := types.SignTx(types.NewTransaction(1, common.Address{}, big.NewInt(100), 0, big.NewInt(0), nil), types.HomesteadSigner{}, key)
|
||||||
balance = new(big.Int).Add(tx5.Value(), new(big.Int).Mul(tx5.Gas(), tx5.GasPrice()))
|
balance = new(big.Int).Add(tx5.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx5.Gas()), tx5.GasPrice()))
|
||||||
|
|
||||||
from, _ = deriveSender(tx5)
|
from, _ = deriveSender(tx5)
|
||||||
pool.currentState.AddBalance(from, balance)
|
pool.currentState.AddBalance(from, balance)
|
||||||
tx5.SetPrivate()
|
tx5.SetPrivate()
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"errors"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
)
|
)
|
||||||
|
@ -103,19 +104,19 @@ var (
|
||||||
//
|
//
|
||||||
// This configuration is intentionally not using keyed fields to force anyone
|
// This configuration is intentionally not using keyed fields to force anyone
|
||||||
// adding flags to the config to also have to set these fields.
|
// adding flags to the config to also have to set these fields.
|
||||||
AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil, false}
|
AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil, false, 32}
|
||||||
|
|
||||||
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
|
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
|
||||||
// and accepted by the Ethereum core developers into the Clique consensus.
|
// and accepted by the Ethereum core developers into the Clique consensus.
|
||||||
//
|
//
|
||||||
// This configuration is intentionally not using keyed fields to force anyone
|
// This configuration is intentionally not using keyed fields to force anyone
|
||||||
// adding flags to the config to also have to set these fields.
|
// adding flags to the config to also have to set these fields.
|
||||||
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil, false}
|
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil, false, 32}
|
||||||
|
|
||||||
TestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil, false}
|
TestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil, false, 32}
|
||||||
TestRules = TestChainConfig.Rules(new(big.Int))
|
TestRules = TestChainConfig.Rules(new(big.Int))
|
||||||
|
|
||||||
QuorumTestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, nil, common.Hash{}, nil, nil, nil, nil, new(EthashConfig), nil, nil, true}
|
QuorumTestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, nil, common.Hash{}, nil, nil, nil, nil, new(EthashConfig), nil, nil, true, 64}
|
||||||
)
|
)
|
||||||
|
|
||||||
// ChainConfig is the core config which determines the blockchain settings.
|
// ChainConfig is the core config which determines the blockchain settings.
|
||||||
|
@ -147,6 +148,7 @@ type ChainConfig struct {
|
||||||
Istanbul *IstanbulConfig `json:"istanbul,omitempty"`
|
Istanbul *IstanbulConfig `json:"istanbul,omitempty"`
|
||||||
|
|
||||||
IsQuorum bool `json:"isQuorum"`
|
IsQuorum bool `json:"isQuorum"`
|
||||||
|
SizeLimit uint64 `json:"txnSizeLimit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
|
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
|
||||||
|
@ -207,6 +209,14 @@ func (c *ChainConfig) String() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ChainConfig) IsValid() error {
|
||||||
|
if c.SizeLimit < 32 || c.SizeLimit > 128 {
|
||||||
|
return errors.New("Genesis transaction size limit must be between 32 and 128")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsHomestead returns whether num is either equal to the homestead block or greater.
|
// IsHomestead returns whether num is either equal to the homestead block or greater.
|
||||||
func (c *ChainConfig) IsHomestead(num *big.Int) bool {
|
func (c *ChainConfig) IsHomestead(num *big.Int) bool {
|
||||||
return isForked(c.HomesteadBlock, num)
|
return isForked(c.HomesteadBlock, num)
|
||||||
|
|
Loading…
Reference in New Issue