On-beacon-chain saved contracts

This is NOT a new idea; it has existed in discussions for a long time. However, it seems useful to have a post explicitly discussing this.

In a sharded blockchain, and especially a stateless sharded blockchain, there will be many pieces of code (or even non-code data such as cryptographic constants) that are shared between many use cases. This includes cryptographic algorithms, smart contract wallet implementations, token contract implementations, etc. To prevent witness sizes from getting too large as a result, we can introduce a functionality where such pieces of code can, at a high cost (eg. 1 ETH per kB), be saved on the beacon chain, and then referenced from shard chain blocks by index.

We would do this by introducing a new beacon chain transaction type, newCode: [code, validator_index, signature], which could be created by a fully inactive validator. This transaction type would be processed as follows:

  1. Verify the signature
  2. Subtract BEACON_CODE_BYTE_FEE * len(code) from the validator’s balance (if the validator has not enough balance, this fails)
  3. Add (code, current_slot_number) to an in-state list of codes: List[Tuple[Bytes, Slot]]

BEACON_CODE_BYTE_FEE would be set to a high amount, eg. 0.001 ETH per byte.

Shard execution would have access to an opcode execute_beacon_code(index, data), which could execute the program with the given index with the given data and return the output (we save the activation slot so that in fraud proofs we know whether or not the code existed at the time a block was executed). We expect all nodes to have access to the beacon chain, so the code is information that they can access.

This is a very useful feature in light of many features of the eth2 roadmap:

  • Account abstraction, where signature verification algorithms need to be part of every piece of account code
  • ERC20 tokens already being abstracted
  • Contracts frequently needing to be yanked across shards, passing all contract code in through a receipt
  • The general move to witness and receipt-based workflow, where every byte of data read needs to be part of a block

In all cases, large pieces of code could be replaced by a simple 4-byte index of which beacon code to use.

Possible extensions

  • Allow beacon codes to be removed, eg. by storing who deposited them and allowing withdrawal with an 8-month delay if the depositor agrees (the depositor address could be changed to 0 to signal a permanent guarantee of non-removal)
  • Make the fee dynamic, eg. targeting a specific beacon chain state growth rate
1 Like

This proposal has a free parameter, BEACON_CODE_BYTE_FEE, that is decided centrally and not by the market. A rate for such data accumulation can be set, and similarly to EIP-1559, increase or decrease BEACON_CODE_BYTE_FEE based on actual use (can set a high floor for minimizing beacon usage). This still isn’t optimal, and can be improved by letting validators change the desired data accumulation rate (similar to gas limit today).

How does this interact with execution environments? Would EEs be able to make similar calls? Would a contract written for one EE be able to call into beacon code for a different EE?

1 Like

Contracts on the beacon chain would not be “for” any specific EE. Any EE could access them.

The equilibrium (price, quantity) is decided by the intersection of the supply and demand curves. The demand curve is set by the market, the supply curve is set by the protocol. It could be a vertical supply curve (fix quantity, market sets the price) or it could be a horizontal supply curve (fix price, market sets the quantity) or even diagonal (fix price / quantity, markets sets price * quantity), but there’s always something that’s fixed.

I suppose we could use arguments from http://ethresear.ch/uploads/default/original/2X/1/197884012ada193318b67c4b777441e4a1830f49.pdf to determine what is more important to fix. Given that support for constrained devices is a goal, it does feel like there is value in setting a limit on storage size, or at least pushing for predictability. So that would lend support for a more diagonal curve. I could actually see price = quantity * k / (t - t0) or even price = (1+k) ** (quantity / (t - t0)) working pretty well.

So would these beacon contracts have to be compiled to WASM?

This should be 1 ETH per kB per kBlocks, right? Each element of the list will produce perpetual costs for all clients for as long as it remains available in the list. Therefore these should be leased, not owned.

You can do rent only in a stateful protocol. This is problematic, because no other party will be able to use it in smart contracts, fearing it won’t be there in the future.

I think the supply needs to take into account the usage over a period, and not just the last block (unless I’m misreading the notation and it’s already there). As a user I care more about the total space I need to store for the beacon chain and less about the size of a single block.

Ideally, the supply side needs to be (somewhat) adjustable by network participants. One could argue that the validators represent the interests of the network/all users, but this is a weak argument. Maybe this question can wait until this is an actually a problem and we have usage data.

I think the fee should be one-time for permanent storage, and we can make the fee high to compensate. We really do want it to be possible to rely on these beacon chain contracts as permanent fixtures.