EIP-3534 - Restricted Chain Context Type Transactions

Created 2021-04-20
Status Stagnant
Category Core
Type Standards Track
Authors
Requires

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:

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.

Specification

Parameters

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

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

ancestorId

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

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

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

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:

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:

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

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.

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

Copyright and related rights waved via CC0.