Alert Source Discuss
🚧 Stagnant Standards Track: Core

EIP-3534: Restricted Chain Context Type Transactions

Authors Isaac Ardis (@whilei)
Created 2021-04-20
Discussion Link https://ethereum-magicians.org/t/eip-3534-restricted-chain-context-transaction-type/6112
Requires EIP-2718, EIP-2930

Simple Summary

Defines a new transaction type with constraints on ancestor block hash, block author, and/or block timestamp.

Abstract

We introduce a new EIP-2718 transaction type with the format 0x4 || rlp([chainId, chainContext, nonce, gasPrice, gasLimit, to, value, data, access_list, yParity, senderR, senderS]).

This proposed chainContext element adds a constraint on the validity of a transaction to a chain segment meeting the referenced value(s). Four contexts are defined as subclasses of this type:

  • segmentId
  • eligibleMinerList
  • ineligibleMinerList
  • expiry

These contexts can be used in arbitrary combinations. Annotated context value combinations are referenced by a composite integer prefix on the annotation.

Motivation

Establish a protocol-based mechanism with which transactions are able to articulate constraints on eligible chain contexts. Generally, these constraints give the consumer (the transactor) an ability to express requirements about the transaction’s relationship to blockchain data and its provenance.

  • Restrict transaction applicability to a chain context that is currently available and reasoned about under some subjective view.
    • Introduces a way for transactions to describe a dependency on their current view of a chain.
  • Restrict transaction applicability to a chain context following some foregoing block (and its transactions).
    • Introduces a way for transactions to describe ancestral dependencies at a “macro” (block) level. Indirectly, this offers a way for a transaction to depend on the presence of another, so long as the dependent transaction is in a different block.
  • Restrict transaction applicability to blocks benefitting, or not benefitting, a preferred/spurned miner address or addresses.
    • Introduces an opportunity/market for miners to compete for consumers’ transactions; under the status quo, the current miner-transaction processing service is almost perfectly homogeneous from the consumer perspective.
  • Restrict transaction applicability time span.
    • Introduces an alternative (to the status quo) way for consumers/transactors to have transactions invalidated/ejected from the transaction pool.

Specification

Parameters

  • FORK_BLOCK_NUMBER TBD
  • TRANSACTION_TYPE_NUMBER 0x4. See EIP-2718.

As of FORK_BLOCK_NUMBER, a new EIP-2718 transaction is introduced with TransactionType TRANSACTION_TYPE_NUMBER.

The EIP-2718 TransactionPayload for this transaction is rlp([chainId, chainContext, nonce, gasPrice, gasLimit, to, value, data, access_list, yParity, senderR, senderS]).

The EIP-2718 ReceiptPayload for this transaction is rlp([status, cumulativeGasUsed, logsBloom, logs]).

Definitions

  • chainContext. The transaction is only valid for blockchain data satisfying ALL OF the annotations.
  • ANNOTATION_COMPOSITE_PREFIX. A positive integer between 1 and 0xff that represents the set of subclass annotations in the chainContext (ie. which chain context subclasses should the provided values be applied to). This value should be the sum of the subclass’ ANNOTATION_PREFIXs.
  • ANNOTATION_PREFIXs are defined for Subclasses as octal-derived positive integers, limited to the set 2^0,2^1,2^2,2^3,2^4,2^5,2^6,2^7.

The chainContext value should be of the form ANNOTATION_COMPOSITE_PREFIX || [{subclass value}...], where

  • ... means “zero or more of the things to the left,” and
  • || denotes the byte/byte-array concatenation operator.

The chainContext value should be encoded as ANNOTATION_COMPOSITE_PREFIX || rlp[{subclass value}...].

Validation

The values defined as subclasses below acts as constraints on transaction validity for specific chain contexts. Transactions defining constraints which are not satisfied by their chain context should be rejected as invalid. Blocks containing invalid transactions should be rejected as invalid themselves, per the status quo.

Subclass Combination

chainContext values annotating more than one subclass reference should provide those values in the following sequential order:

  1. ANCESTOR_ID
  2. ELIGIBLE_MINER_LIST
  3. INELIGIBLE_MINER_LIST
  4. EXPIRY

As above, the ANNOTATION_COMPOSITE_PREFIX should be the sum of the designated subclass’ ANNOTATION_PREFIXs.

Subclasses

  • An ANNOTATION_PREFIX value is used to represent each of the available context subclasses.

ancestorId

  • ANNOTATION_PREFIX 1.
  • ANCESTOR_ID bytes. A byte array between 4 and 12 bytes in length.

The ANCESTOR_ID is a reference to a specific block by concatenating the byte representation of a block number and the first 4 bytes of its hash. The block number’s should be encoded as a big endian value and should have left-padding 0’s removed. The block number value may be omitted in case of reference to the genesis block.

The ANCESTOR_ID value should be RLP encoded as a byte array for hashing and transmission.

eligibleMinerList

  • ANNOTATION_PREFIX 2.
  • ELIGIBLE_MINER_LIST [address...]. A list of addresses.
  • MAX_ELEMENTS 3. The maximum number of addresses that can be provided.

The ELIGIBLE_MINER_LIST value is an array of unique, valid addresses. Any block containing a transaction using this value must have a block beneficiary included in this set.

The ELIGIBLE_MINER_LIST value should be of the type [{20 bytes}+], where + means “one or more of the thing to the left.” Non-unique values are not permitted.

The ELIGIBLE_MINER_LIST value should be RLP encoded for hashing and transmission.

An ELIGIBLE_MINER_LIST value may NOT be provided adjacent to an INELIGIBLE_MINER_LIST value.

ineligibleMinerList

  • ANNOTATION_PREFIX 4.
  • INELIGIBLE_MINER_LIST [address...]. A list of addresses.
  • MAX_ELEMENTS 3. The maximum number of addresses that can be provided.

The INELIGIBLE_MINER_LIST value is an array of unique, valid addresses. Any block containing a transaction using this value must not have a block beneficiary included in this set.

The INELIGIBLE_MINER_LIST value should be of the type [{20 bytes}+], where + means “one or more of the thing to the left.” Non-unique values are not permitted.

The INELIGIBLE_MINER_LIST value should be RLP encoded for hashing and transmission.

An INELIGIBLE_MINER_LIST value may NOT be provided adjacent to an ELIGIBLE_MINER_LIST value.

expiry

  • ANNOTATION_PREFIX 8.
  • EXPIRY integer. A positive, unsigned scalar.

The EXPIRY value is a scalar equal to the maximum valid block timestamp for a block including this transaction.

The EXPIRY value should be RLP encoded as an integer for hashing and transmission.

Rationale

Subclasses

Subclasses are defined with a high level of conceptual independence, and can be modified and/or extended independently from this EIP. Their specification definitions allow arbitrary mutual (AND) combinations.

This design is intended to form a proposal which offers a concrete set of specifics while doing so with enough flexibility for extension or modification later.

ANNOTATION_PREFIX

ANNOTATION_PREFIX values’ use of octal-derived values, ie. 1, 2, 4, 8, 16, 32, 64, 128, follows a conventional pattern of representing combinations from a limited set uniquely and succinctly, eg. Unix-style file permissions. This EIP defines four of the eight possible context subclasses; this seems to leave plenty of room for future growth in this direction if required. If this limit is met or exceeded, doing so will require a hard fork de facto (by virtue of making consensus protocol facing changes to transaction validation schemes), so revising this scheme as needed should be only incidental and trivial.

ancestorId

Constrains the validity of a transaction by referencing a prior canonical block by number and hash. The transaction is only valid when included in a block which has the annotated block as an ancestor.

Practically, the “designated allowable chain segment” can be understood as the segment of blocks from 0..ancestorId inclusive.

Redundancy to chainId

This pattern can be understood as a correlate of EIP-155’s chainId specification. EIP155 defines the restriction of transactions between chains; limiting the applicability of any EIP-155 transaction to a chain with the annotated ChainID. ancestorId further restricts transaction application to one subsection (“segment”) of one chain.

From this constraint hierarchy, we note that an implementation of ancestorId can make chainId conceptually redundant.

So why keep chainId?

chainId is maintained as an invariant because:

  • The use of the transaction type proposed by this EIP is optional, implying the continued necessity of chainId in the protocol infrastructure and tooling for legacy and other transaction types.
  • The presence of ancestorId in the transaction type proposed by this EIP is optional. If the value is not filled by an RCC transaction, the demand for chainId remains.
  • A chainId value is not necessarily redundant to ancestorId, namely in cases where forks result in living chains. For example, an ancestorId reference to block 1_919_999 would be ambiguous between Ethereum and Ethereum Classic.
  • It would be possible to specify the omission of chainId in case of ancestorId’s use. This would add infrastructural complexity for the sake of removing the few bytes chainId typically requires; we do not consider this trade-off worth making.
    • chainId is used as the v value (of v,r,s) in the transaction signing scheme; removing or modifying this incurs complexity at a level below encoded transaction fields, demanding additional infrastructural complexity for implementation.
  • The proposed design for ancestorId does not provide perfect precision (at the benefit of byte-size savings). In the small chance that the value is ambiguous, the chainId maintains an infallible guarantee for a transaction’s chain specificity.

eligibleMinerList

The transaction is only valid when included in a block having an etherbase contained in the annotated list of addresses. The use of “whitelist” (eligibleMinerList) in conjunction with a “blacklist” (ineligibleMinerList) is logically inconsistent; their conjunction is not allowed.

A MAX_ELEMENTS limit of 3 is chosen to balance the interests of limiting the potential size of transactions, and to provide a sufficient level of articulation for the user. At the time of writing, the top 3 miners of Ethereum (by block, measured by known public addresses) account for 52% of all blocks produced.

ineligibleMinerList

The transaction is only valid when included in a block having an etherbase not contained in the annotated list of addresses. The use of “blacklist” (ineligibleMinerList) in conjunction with a “whitelist” (eligibleMinerList) is logically inconsistent; their conjunction is not allowed.

A MAX_ELEMENTS limit of 3 is chosen to balance the interests of limiting the potential size of transactions, and to provide a sufficient level of articulation for the user. At the time of writing, the top 3 miners of Ethereum (by block, measured by known public addresses) account for 52% of all blocks produced.

expiry

The transaction is only valid when included in a block having a timestamp less than the value annotated. A positive integer is used because that corresponds to the specified type of block timestamp header values.

Subclass Combination

Since subclasses use octal-based values for ANNOTATION_PREFIX, they can be distinguishably combined as sums, provided as we assume annotation cardinality (ie ordering). For example:

  • ANNOTATION_PREFIX 1 signals ancestorId exclusively.
  • ANNOTATION_PREFIX 2 signals eligibleMinerList exclusively.
  • ANNOTATION_PREFIX 4 signals ineligibleMinerList exclusively.
  • ANNOTATION_PREFIX 8 signals expiry exclusively.
  • ANNOTATION_PREFIX 1+2=3 combines ancestorId and eligibleMinerList.
  • ANNOTATION_PREFIX 1+4=5 combines ancestorId and ineligibleMinerList.
  • ANNOTATION_PREFIX 1+8=9 combines ancestorId and expiry.
  • ANNOTATION_PREFIX 1+2+8=11 combines ancestorId and eligibleMinerList and expiry.
  • ANNOTATION_PREFIX 1+4+8=13 combines ancestorId and ineligibleMinerList and expiry.
  • ANNOTATION_PREFIX 2+4=6 is NOT PERMITTED. It would combine eligibleMinerList and ineligibleMinerList.
  • ANNOTATION_PREFIX 1+2+4+8=15 is NOT PERMITTED. It would combine eligibleMinerList and ineligibleMinerList (and ancestorId and expiry).

Since ordering is defined and demanded for multiple values, annotated references remain distinguishable. For example:

  • chainContext 3[e4e1c0e78b1ec3,[Df7D7e053933b5cC24372f878c90E62dADAD5d42]] - Transaction can only be included in a block having a canonical ancestor block numbered 15_000_000 and with a hash prefixed with the bytes e78b1ec3, and if the containing block uses Df7D7e053933b5cC24372f878c90E62dADAD5d42 as the beneficiary.
  • chainContext 10[[Df7D7e053933b5cC24372f878c90E62dADAD5d42],1619008030] - Transaction can only be included in a block naming Df7D7e053933b5cC24372f878c90E62dADAD5d42 as the etherbase beneficiary, and which has a timestamp greater than 1619008030 (Wed Apr 21 07:27:10 CDT 2021).

EIP-2930 Inheritance

The EIP-2930 Optional Access List Type Transaction is used as an assumed “base” transaction type for this proposal. However, this is NOT a conceptual dependency; the included accessList portion of this proposal (the only differential from post-EIP-155 legacy transaction fields) can readily be removed. Standing on the shoulders of EIP-2930 is only intended to support and further the adoption of next-generation transactions.

Signature target

The signature signs over the transaction type as well as the transaction data. This is done to ensure that the transaction cannot be “re-interpreted” as a transaction of a different type.

Backwards Compatibility

There are no known backward compatibility issues.

Test Cases

Segment ID Block Number Canonical Block Hash
e78b1ec3 0 0xe78b1ec31bcb535548ce4b6ef384deccad1e7dc599817b65ab5124eeaaee3e58
01e78b1ec3 1 0xe78b1ec31bcb535548ce4b6ef384deccad1e7dc599817b65ab5124eeaaee3e58
e4e1c0e78b1ec3 15_000_000 0xe78b1ec31bcb535548ce4b6ef384deccad1e7dc599817b65ab5124eeaaee3e58
e8d4a50fffe78b1ec3 999_999_999_999 0xe78b1ec31bcb535548ce4b6ef384deccad1e7dc599817b65ab5124eeaaee3e58
7fffffffffffffffe78b1ec3 9223372036854775807 0xe78b1ec31bcb535548ce4b6ef384deccad1e7dc599817b65ab5124eeaaee3e58

Further test cases, TODO.

Security Considerations

Why 4 bytes of a block hash is “safe enough” for the ancestorId

TL;DR: The chance of an ineffectual ancestorId is about 1 in between ~4 billion and ~40 billion, with the greater chance for intentional duplication scenarios, eg. malicious reorgs.

If a collision does happen, that means the transaction will be valid on both segments (as is the case under the status quo).

Four bytes, instead of the whole hash (32 bytes), was chosen only to reduce the amount of information required to cross the wire to implement this value. Using the whole hash would result in a “perfectly safe” implementation, and every additional byte reduces the chance of collision exponentially.

The goal of the ancestorId is to disambiguate one chain segment from another, and in doing so, enable a transaction to define with adequate precision which chain it needs to be on. When a transaction’s ancestorId references a block, we want to be pretty sure that that reference won’t get confused with a different block than the one the author of the transaction had in mind.

We assume the trait of collision resistance is uniformly applicable to all possible subsets of the block hash value, so our preference of using the first 4 bytes is arbitrary and functionally equivalent to any other subset of equal length.

For the sake of legibility and accessibility, the following arguments will reference the hex representation of 4 bytes, which is 8 characters in length, eg. e78b1ec3.

The chance of a colliding ancestorId is 1/(16^8=4_294_967_296) times whatever we take the chance of the existence of an equivalently-numbered block (on an alternative chain) to be. Assuming a generous ballpark chance of 10% (1/10) for any given block having a public uncle, this yields (1/(16^8=4_294_967_296) * 1/10. Note that this ballpark assumes “normal” chain and network behavior. In the case of an enduring competing chain segment, this value rises to 100% (1).

eligibleMinerList

Miners who do not find themselves listed in an annotated eligibleMinerList should be expected to immediately remove the transaction from their transaction pool.

In a pessimistic outlook, we should also expect that these ineligible nodes would not offer rebroadcasts of these transactions, potentially impacting the distribution (and availability) of the transactions to their intended miners. On the other hand, miners are incentivized to make themselves available for reception of such transactions, and there are many ways this is feasible both on-network and off-.

The author of a transaction using the eligibleMinerList must assume that the “general availability” of the blockchain state database for such a transaction will be lower than a nonrestrictive transaction (since only a subset of miners will be able to process the transaction).

A final consideration is the economics of a whitelisted miner concerning the processing order of transactions in which they are whitelisted and those without whitelists. Transactions without whitelists would appear at first glean to be more competitive, and thus should be processed with priority. However, miners following such a strategy may find their reputation diminished, and, in the worst case, see the assertive preferences of transaction authors shift to their competitors and beyond their reach.

ineligibleMinerList

In addition to the concerns and arguments presented by eligibleMinerList above, there is a unique concern for ineligibleMinerList: in order for a miner entity to avoid ineligibility by a blacklist, they only need to use an alternative adhoc address as the block beneficiary. In principle, this is ineluctable.

However, there are associated costs to the “dodging” miner that should be considered.

  • The creation of an account requires time and energy. But indeed, this work can be done at any convenient time and circumstance. Probably marginal, but non-zero.
  • The transfer of funds from multiple accounts requires a commensurate number of transactions. Block rewards are applied after transactions are processed, so the miner is unable to simultaneously shift funds from an adhoc account to a target account in the same block they mine (which would otherwise be a “free” transaction).
  • In using an adhoc address to dodge a blacklist, the miner may also cause their ineligibility from contemporary whitelist transactions.

Validation costs

Miner lists and expiry depend on easily cached and contextually available conditions (ie. the containing block header). The infrastructural overhead costs for enforcing these validations are expected to be nominal.

Validation of ancestorId demands the assertion of a positive database hit by block number (thereby cross-referencing a stored block’s hash). This necessary lookup can be (and maybe already is) cached, but we must expect less than 100% hits on cached values, since the lookup value is arbitrary. With that in mind, however, the value provided to a transaction using a deep ancestorId is increasingly marginal, so we should expect most transactions using this field to use a relatively small set of common, shallow, cache-friendly values.

Transaction size increase

The proposed additional fields potentially increase transaction size. The proposed fields are not associated with any gas costs, establishing no protocol-defined economic mitigation for potential spam. However, transactions which are considered by a miner to be undesirable can be simply dropped from the transaction pool and ignored.

Copyright and related rights waved via CC0.

Citation

Please cite this document as:

Isaac Ardis (@whilei), "EIP-3534: Restricted Chain Context Type Transactions [DRAFT]," Ethereum Improvement Proposals, no. 3534, April 2021. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-3534.