Skip to content

feat(tests): extend type-0 transaction RLP validity tests#2

Open
danceratopz wants to merge 8 commits into
chfast:invalid-tx-rlp-testsfrom
danceratopz:invalid-tx-rlp-tests-suggestions
Open

feat(tests): extend type-0 transaction RLP validity tests#2
danceratopz wants to merge 8 commits into
chfast:invalid-tx-rlp-testsfrom
danceratopz:invalid-tx-rlp-tests-suggestions

Conversation

@danceratopz

Copy link
Copy Markdown

Description

Suggestions on top of ethereum#3156.

  • Fixes:
    • Accept exception lists where clients legitimately report different errors for the same vector: header_declares_less (an EOF or a size error) and v_29 (post EIP-155 clients may derive a chain id from any v other than 27 or 28, as documented in test_bad_v_r_s).
    • Correct the field overflow docstring: The spec decodes the nonce as a 256-bit scalar (the 64-bit bound is EIP-2681 validation), and v is also 256-bit bounded but lacks a field-specific decoding exception.
    • Fund only senders that actually send: The corrupted transactions' senders never send, so deferred funding via pre.fund_eoa() fails under execute; with amount=0 the whole module now passes execute hive --fork=Prague (36/36 on besu).
  • New cases, each verified against EELS decoding and validation at Frontier, London and Cancun:
    • r and s in test_field_as_list, porting TRANSCT_{r,s}value_GivenAsListCopier.
    • test_non_canonical_single_byte: Single-byte nonce behind a 0x81 string header, porting RLPIncorrectByteEncoding{00,01,127}Copier.
    • test_data_size_leading_zeros: Long-form data string header with a zero-padded size, porting RLPArrayLengthWithFirstZerosCopier.
    • v_zero in test_invalid_signature_values.
  • Cite more legacy fillers whose malformation class is already covered; each was inspected at the pinned commit to confirm the corruption and declared exception match.

Declare exception lists where clients legitimately report different
errors for the same malformed transaction:

- `header_declares_less`: the mutation leaves both a truncated final
  field and a trailing byte at the top level, so clients report it as
  either an EOF or a size error.
- `v_29`: post EIP-155 clients may derive a chain id from any v other
  than 27 or 28 and reject the mismatch instead of the signature, as
  already documented in `test_bad_v_r_s`.
The nonce is decoded as a 256-bit scalar by the spec; the 64-bit bound
is an EIP-2681 validation rule, not a decoding one. Also note that the
signature v is a bounded 256-bit field whose oversized encoding is
uncovered only because no field-specific decoding exception exists.
Extend `test_field_as_list` to the signature r and s fields, porting
`TRANSCT_rvalue_GivenAsListCopier` and `TRANSCT_svalue_GivenAsListCopier`
with the same `RLP_INVALID_SIGNATURE_R`/`_S` exceptions the legacy
suite declares. The gas price and v fields remain uncovered for lack
of a field-specific decoding exception.
Encode the single-byte nonce payload behind a one-byte string header
(0x8101) instead of as the byte itself. This ports the
`RLPIncorrectByteEncoding{00,01,127}Copier` legacy tests, which corrupt
the nonce this way and declare `RLP_LEADING_ZEROS_NONCE_SIZE`.
Encode the size of the data field's long-form string header with a
leading zero byte, porting `RLPArrayLengthWithFirstZerosCopier` with
the `RLP_LEADING_ZEROS_DATA_SIZE` exception it declares. This covers
the string-header variant of the list-header case already tested by
the `list_size_leading_zeros` mutation.
A zero v is well-encoded (empty payload) but is neither 27, 28 nor an
EIP-155 value. Declare `INVALID_CHAINID` as an acceptable alternative
for the same reason as the other invalid v cases: post EIP-155 clients
may derive a chain id from any v other than 27 or 28.
Add `ported_from` references for legacy fillers whose malformation
class is already exercised by an existing case:

- Leading zeros: the `tt{Nonce,GasPrice,GasLimit,Value}` zero-prefixed
  fillers and the `TRANSCT_*_Prefixed0000` copiers.
- Overflow: the `TRANSCT_{r,s}value_TooLarge` copiers.
- Address size: `AddressMoreThan20` and the `TRANSCT_to_*` copiers.
- Field as list: the remaining `TRANSCT_*_GivenAsList` copiers.
- Structure: `RLPTransactionGivenAsArray`, matching the
  `tx_as_byte_string` mutation.

All referenced fillers were inspected at the pinned commit to confirm
the corruption and declared exception match the covering case.
In execute mode, `pre.fund_eoa()` defers the funding amount until the
EOA sends a transaction; an EOA that never sends one fails the run
with "Sender balance must be set before sending". The senders of the
corrupted transactions never send: only their raw serialization is
submitted, expecting rejection. Fund them with `amount=0` so execute
mode derives an address without scheduling a funding transaction.

The signing keys are derived from the account content, so the
corrupted vectors' bytes change; all vectors were re-verified against
EELS decoding and validation at Frontier, London and Cancun.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant