Skip to content

Commit

Permalink
[Core + API + Node] Add raw tx size limitation (#2382)
Browse files Browse the repository at this point in the history
* Define constants for tx-data and check size limit in tx-pool
* Check for raw data size limitation at RPC layer
* Check for raw data size limitation at Network layer
  • Loading branch information
fxfactorial authored Mar 5, 2020
1 parent 82952fe commit 1e5d420
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 3 deletions.
6 changes: 3 additions & 3 deletions core/tx_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ var DefaultTxPoolConfig = TxPoolConfig{
AccountQueue: 64,
GlobalQueue: 1024,

Lifetime: 3 * time.Hour,
Lifetime: 30 * time.Minute,

Blacklist: map[common.Address]struct{}{},
}
Expand Down Expand Up @@ -657,8 +657,8 @@ func (pool *TxPool) validateTx(tx types.PoolTransaction, local bool) error {
if tx.ShardID() != pool.chain.CurrentBlock().ShardID() {
return errors.WithMessagef(ErrInvalidShard, "transaction shard is %d", tx.ShardID())
}
// Heuristic limit, reject transactions over 32KB to prevent DOS attacks
if tx.Size() > 32*1024 {
// For DOS prevention, reject excessively large transactions.
if tx.Size() >= types.MaxPoolTransactionDataSize {
return errors.WithMessagef(ErrOversizedData, "transaction size is %s", tx.Size().String())
}
// Transactions can't be negative. This may never happen using RLP decoded
Expand Down
7 changes: 7 additions & 0 deletions core/types/tx_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ import (
staking "github.com/harmony-one/harmony/staking/types"
)

const (
//MaxPoolTransactionDataSize is a 32KB heuristic data limit for DOS prevention
MaxPoolTransactionDataSize = 32 * 1024
//MaxEncodedPoolTransactionSize is a heuristic raw/encoded data size limit. It has an additional 10KB for metadata
MaxEncodedPoolTransactionSize = MaxPoolTransactionDataSize + (10 * 1024)
)

var (
// ErrUnknownPoolTxType is returned when attempting to assert a PoolTransaction to its concrete type
ErrUnknownPoolTxType = errors.New("unknown transaction type in tx-pool")
Expand Down
9 changes: 9 additions & 0 deletions internal/hmyapi/apiv1/transactionpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/harmony-one/harmony/accounts"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/rawdb"
"github.com/harmony-one/harmony/core/types"
internal_common "github.com/harmony-one/harmony/internal/common"
Expand Down Expand Up @@ -209,6 +210,10 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen
func (s *PublicTransactionPoolAPI) SendRawStakingTransaction(
ctx context.Context, encodedTx hexutil.Bytes,
) (common.Hash, error) {
if len(encodedTx) >= types.MaxEncodedPoolTransactionSize {
err := errors.Wrapf(core.ErrOversizedData, "encoded tx size: %d", len(encodedTx))
return common.Hash{}, err
}
tx := new(staking.StakingTransaction)
if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
return common.Hash{}, err
Expand All @@ -224,6 +229,10 @@ func (s *PublicTransactionPoolAPI) SendRawStakingTransaction(
// SendRawTransaction will add the signed transaction to the transaction pool.
// The sender is responsible for signing the transaction and using the correct nonce.
func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error) {
if len(encodedTx) >= types.MaxEncodedPoolTransactionSize {
err := errors.Wrapf(core.ErrOversizedData, "encoded tx size: %d", len(encodedTx))
return common.Hash{}, err
}
tx := new(types.Transaction)
if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
return common.Hash{}, err
Expand Down
9 changes: 9 additions & 0 deletions internal/hmyapi/apiv2/transactionpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/harmony-one/harmony/accounts"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/rawdb"
"github.com/harmony-one/harmony/core/types"
internal_common "github.com/harmony-one/harmony/internal/common"
Expand Down Expand Up @@ -207,6 +208,10 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen
func (s *PublicTransactionPoolAPI) SendRawStakingTransaction(
ctx context.Context, encodedTx hexutil.Bytes,
) (common.Hash, error) {
if len(encodedTx) >= types.MaxEncodedPoolTransactionSize {
err := errors.Wrapf(core.ErrOversizedData, "encoded tx size: %d", len(encodedTx))
return common.Hash{}, err
}
tx := new(staking.StakingTransaction)
if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
return common.Hash{}, err
Expand All @@ -222,6 +227,10 @@ func (s *PublicTransactionPoolAPI) SendRawStakingTransaction(
// SendRawTransaction will add the signed transaction to the transaction pool.
// The sender is responsible for signing the transaction and using the correct nonce.
func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error) {
if len(encodedTx) >= types.MaxEncodedPoolTransactionSize {
err := errors.Wrapf(core.ErrOversizedData, "encoded tx size: %d", len(encodedTx))
return common.Hash{}, err
}
tx := new(types.Transaction)
if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
return common.Hash{}, err
Expand Down
9 changes: 9 additions & 0 deletions node/node_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
proto_discovery "github.com/harmony-one/harmony/api/proto/discovery"
proto_node "github.com/harmony-one/harmony/api/proto/node"
"github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/types"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"github.com/harmony-one/harmony/internal/ctxerror"
Expand Down Expand Up @@ -187,6 +188,10 @@ func (node *Node) HandleMessage(content []byte, sender libp2p_peer.ID) {
}

func (node *Node) transactionMessageHandler(msgPayload []byte) {
if len(msgPayload) >= types.MaxEncodedPoolTransactionSize {
utils.Logger().Warn().Err(core.ErrOversizedData).Msgf("encoded tx size: %d", len(msgPayload))
return
}
if len(msgPayload) < 1 {
utils.Logger().Debug().Msgf("Invalid transaction message size")
return
Expand All @@ -208,6 +213,10 @@ func (node *Node) transactionMessageHandler(msgPayload []byte) {
}

func (node *Node) stakingMessageHandler(msgPayload []byte) {
if len(msgPayload) >= types.MaxEncodedPoolTransactionSize {
utils.Logger().Warn().Err(core.ErrOversizedData).Msgf("encoded tx size: %d", len(msgPayload))
return
}
if len(msgPayload) < 1 {
utils.Logger().Debug().Msgf("Invalid staking transaction message size")
return
Expand Down

0 comments on commit 1e5d420

Please sign in to comment.