Skip to content

Commit e73a64e

Browse files
authored
Merge pull request #431 from bane-labs/ensure-envelope-gaslimit
contracts: move encrypted tx gas limit check to consensus level
2 parents d6791ac + 8a63640 commit e73a64e

File tree

5 files changed

+35
-4
lines changed

5 files changed

+35
-4
lines changed

antimev/envelope.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ import (
99
"github.com/ethereum/go-ethereum/core/systemcontracts"
1010
"github.com/ethereum/go-ethereum/core/types"
1111
"github.com/ethereum/go-ethereum/crypto/tpke"
12+
"github.com/ethereum/go-ethereum/params"
1213
)
1314

15+
// MinEncryptedGasLimit is the minimum required gas limit for encrypted transaction.
16+
// It is set to be equal to a simple transfer execution cost since it is assumed that
17+
// minimum valid encrypted transaction structure is a simple transfer.
18+
const MinEncryptedGasLimit = uint32(params.TxGas)
19+
1420
var (
1521
// EncryptedDataPrefix is the prefix of Envelope transaction's data. It's used to
1622
// distinguish simple transactions that have GovernanceRewardProxy contract as a
@@ -75,7 +81,7 @@ func GetEncryptedHash(envelope *types.Transaction) common.Hash {
7581

7682
// GetEncryptedGas returns the gas limit of inner encrypted transaction specified in an
7783
// unencrypted part of Envelope data. Passing non-Envelope as an argument is a no-op.
78-
func GetEncryptedGas(envelope *types.Transaction) uint32 {
84+
func GetEncryptedGas(envelopeData []byte) uint32 {
7985
gasOffset := EncryptedDataPrefixLen + EncryptedDataRoundLen
80-
return binary.BigEndian.Uint32(envelope.Data()[gasOffset : gasOffset+EncryptedDataGasLen])
86+
return binary.BigEndian.Uint32(envelopeData[gasOffset : gasOffset+EncryptedDataGasLen])
8187
}

consensus/dbft/dbft.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,7 @@ func (c *DBFT) validateDecryptedTx(head *types.Header, decryptedTx *types.Transa
12631263
return fmt.Errorf("decryptedTx hash mismatch: expected %s, got %s", expectedH, decryptedTx.Hash())
12641264
}
12651265
// Ensure decrypted gas limit is the same as the envelope declared
1266-
expectedG := antimev.GetEncryptedGas(envelope)
1266+
expectedG := antimev.GetEncryptedGas(envelope.Data())
12671267
if decryptedTx.Gas() != uint64(expectedG) {
12681268
return fmt.Errorf("decryptedTx gas limit mismatch: expected %v, got %v", expectedG, decryptedTx.Gas())
12691269
}

core/state_transition.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,16 @@ func (st *StateTransition) preCheck() error {
335335
return fmt.Errorf("%w: address %v, gasLimit %v, policy maxEnvelopeGasLimit %v, ", ErrGasLimitReached, msg.From.Hex(), msg.GasLimit,
336336
envelopeGasLimit)
337337
}
338+
// Check that encrypted transaction gas limit satisfies the minimum required gas limit.
339+
encryptedGasLimit := antimev.GetEncryptedGas(msg.Data)
340+
if encryptedGasLimit < antimev.MinEncryptedGasLimit {
341+
return fmt.Errorf("invalid encrypted transaction gas limit: required at least %v, got %v", antimev.MinEncryptedGasLimit, encryptedGasLimit)
342+
}
343+
// The gas limit of Envelope transaction should be enough to cover encrypted transaction
344+
// execution.
345+
if msg.GasLimit < uint64(encryptedGasLimit) {
346+
return fmt.Errorf("invalid envelope gas limit: at least %d is required for encrypted transaction execution, have %d", encryptedGasLimit, msg.GasLimit)
347+
}
338348
var envelopeFee = st.state.GetState(systemcontracts.PolicyProxyHash, systemcontracts.GetEnvelopeFeeStateHash()).Big()
339349
minGasTipCap.Add(minGasTipCap, envelopeFee)
340350
}

core/txpool/errors.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ var (
4545
// maximum allowance of the current block.
4646
ErrGasLimit = errors.New("exceeds block gas limit")
4747

48+
// ErrEnvelopeGasLimit is returned if an Envelope transaction's requested gas limit
49+
// doesn't satisfy verification criteria.
50+
ErrEnvelopeGasLimit = errors.New("invalid Envelope gas limit")
51+
4852
// ErrNegativeValue is a sanity error to ensure no one is able to specify a
4953
// transaction with a negative value.
5054
ErrNegativeValue = errors.New("negative value")

core/txpool/validation.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,18 @@ func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, op
220220
if antimev.IsEnvelope(tx) {
221221
var envelopeGasLimit = opts.State.GetState(systemcontracts.PolicyProxyHash, systemcontracts.GetMaxEnvelopeGasLimitStateHash()).Big()
222222
if new(big.Int).SetUint64(tx.Gas()).Cmp(envelopeGasLimit) > 0 {
223-
return fmt.Errorf("%w: policy maxEnvelopeGasLimit allowed %v, gas %v", ErrGasLimit, envelopeGasLimit, tx.Gas())
223+
return fmt.Errorf("%w: policy maxEnvelopeGasLimit allowed %v, gas %v", ErrEnvelopeGasLimit, envelopeGasLimit, tx.Gas())
224+
}
225+
// Assuming that encrypted transaction is at least a simple transfer, its gas limit
226+
// must be enough to cover simple transfer execution.
227+
encryptedGasLimit := antimev.GetEncryptedGas(tx.Data())
228+
if encryptedGasLimit < antimev.MinEncryptedGasLimit {
229+
return fmt.Errorf("invalid encrypted transaction gas limit: required at least %v, got %v", antimev.MinEncryptedGasLimit, encryptedGasLimit)
230+
}
231+
// The gas limit of Envelope transaction should be enough to cover encrypted transaction
232+
// execution.
233+
if tx.Gas() < uint64(encryptedGasLimit) {
234+
return fmt.Errorf("%w: at least %d is required for encrypted transaction execution, have %d", ErrEnvelopeGasLimit, encryptedGasLimit, tx.Gas())
224235
}
225236
// Add envelope fee on top of minGasTipCap check
226237
var envelopeFee = opts.State.GetState(systemcontracts.PolicyProxyHash, systemcontracts.GetEnvelopeFeeStateHash()).Big()

0 commit comments

Comments
 (0)