This EIP introduces a new Introduces a new EIP-6404 transaction profile with the express purpose of allowing signing of transaction payloads with alternative signature algorithms. It also creates a new precompile to be able to decode these additional signature algorithms.
2025-06-21: Identified an issue where the additional_info is not signed and can be modified. Fixed via setting r to 0, but s to keccak256(alg_type || signature_info).
2025-08-06: Reworked the abstract and the title to be more descriptive
2025-08-07: Huge rework to be EIP-6404 based rather than RLP (moved back to draft)
2025-10-04: Reintroduced RLP support and made several smaller modifications to fix some malleability concerns
2025-11-05: Removed SSZ support (as it may be handled natively by EIP-6404) and clarified some missing details PR
I’d extend this proposal with support for patching ecrecover as well. Fixing the outer transaction signature without fixing ecrecover will only solve part of the PQ problem.
One approach that’s been tossed around is to embed a list of tuples in the transaction that contain a mapping from the ecrecover arguments to the real signature/algorithm data. I haven’t thought that through entirely, but hopefully it’s a starting point.
The EIP-7702 problem was solved by adding space for additional signatures after the transaction, I don’t know how practical this would be but it was one of my better solutions. (edit: I also added the NULL algorithm for edge cases where the initial signature is secp256k1 but the others are not)
I also patched ecrecover instead of using a mapping as that seemed a bit too complex, I made any v recovery value v > 0xFF && v <= 0xFFFF trigger the contract to be treated as an Algorithmic. Might still need to work on the name, but for now Algorithmic transaction rolls of the tounge. I am going to introduce a new precompile, with a name similar to sigrecover as the “overload the v value” seemed somewhat hacky and may break some implementations.
After a conversation with a member of the Ethereum Foundation, I have rebased this EIP onto EIP-6404. I’d like some feedback on the newer version before merging it into the main repo.
If the length of the input is already known, we don’t need to encode the length of the signature part. You can just assume that input[33:] is the signature.
def sigrecover_precompile(input: Bytes) -> Bytes:
# Recover signature length and type
assert(len(input) >= 33)
hash: Hash32 = input[:32]
algorithm_type: uint8 = input[32]
signature: Bytes = input[33:] # len(signature) == len(input) - 33
# Ensure the algorithm exists and signature is correct size
if algorithm_type not in Algorithms:
return ExecutionAddress(0x0)
alg = Algorithms[algorithm_type]
# Sig length must be smaller than alg.MAX_SIZE and
# equal to the remaining call data
if len(signature) > alg.MAX_SIZE:
return ExecutionAddress(0x0)
# Run verify function
try:
return alg.verify(signature, hash)
except:
return ExecutionAddress(0x0)
This would be a better idea. I believe I initally put in the checks as a sort of anti-DOS measure, but that is obtained via memory and calldata costs. I’ll redo the sigrecover section.