owned this note
owned this note
Published
Linked with GitHub
# Simple shard data fee market
The following is a simple market for shard data that uses an agreed upon contract on eth1 (or the eth1 shard) for coordination. It relies upon some eth2 system level accesses including access to: the validator set, recent slot shard data roots, and recent shard proposer indices.
## Contract interface and storage
### Types
* `BLSPubkey: bytes48`
* `BLSSignature: bytes96`
* `Eth1Addr: bytes20`
* `ValidatorIndex: uint64`
* `Epoch: uint64`
* `Slot: uint64`
* `Root: bytes32`
* `Bounty: {owner: Eth1Addr, data_root: Root, value: Wei, expiration: Slot, consumed: Bool, withdrawn: Bool}`
### Storage
* `validator_addrs: map[ValidatorIndex -> ETH1Addr]`
* `bounties: list[Bounty]`
### Functions
#### `register_validator`
*Registers an eth1 address for a given validator index*
`register_validator(index: ValidatorIndex, eth1_addr: ETH1Addr, registration_proof: BLSSignature)`
* `assert num_validators() > index`
* let `validator = get_validator_by_index(index)`
* let `pubkey = validator.pubkey`
* Check that `registration_proof` is a valid BLS signature for `pubkey` over `eth1_addr` (probably with some signature domain)
* If invalid: exit
* set `validator_addrs[index] = eth1_addr`
#### `post_bounty`
*Posts a bounty for `data_root` that expires at `expiration` slot. Sets an eth1 `owner` with the ability to withdraw if expiration is breached*
`post_bounty(owner: Eth1Addr, data_root: Root, expiration: Slot) payable`
* _maybe_ `assert msg.value > 0`
* Create `bounty = Bounty(owner, data_root, msg.value, expiration, False, False)`
* Append `bounty` to `bounties`
#### `claim_bounty`
*Allows for `bounty` define by `bounty_index` to be claimed if `bounty.data_root` is the shard block root for `shard` at `shard_slot`. Bounties are paid to the proposer of the shard block and proposers must be pre-registered in `validator_addrs`*
`claim_bounty(bounty_index: uint64, shard: Shard, shard_slot: Slot)`
* `assert len(bounties) > bounty_index`
* let `bounty = bounties[bounty_index]`
* let `proposer_index = get_shard_proposer_index_at_slot(shard, shard_slot)`
* `assert validator_addrs[proposer_index] != 0x00`
* `assert not bounty.consumed`
* `assert timestamp_to_slot(block.timestamp) < bounty.expiration`
* `assert get_shard_root_at_slot(shard, shard_slot) == bounty.data_root`
* set `bounty.consumed = True`
* send `bounty.value` to `validator_addrs[proposer_index]`
#### `withdraw_bounty`
*Allows for a `bounty` to be withdrawn if it is expired and not yet consumed. Withdrawals go to `eth1.owner`.*
`withdraw_bounty(bounty_index: uint64)`
* `assert len(bounties) > bounty_index`
* let `bounty = bounties[bounty_index]`
* `assert not bounty.consumed`
* `assert timestamp_to_slot(block.timestamp) >= bounty.expiration`
* `assert not bounty.withdrawn`
* set `bounty.withdrawn = True`
* send `bounty.value` to `bounty.owner`
## Things to consider
### Expiration reform
A `bounty` might want to separate out `on_chain_expiration` vs `claim_expiration`. The former being the slot by which the data should make it on chain, and the latter being how long the validator can go to claim the bounty. A user might want an aggressive `on_chain_expiration` to see data get on chain quickly, but the validator might want some breathing room to claim the bounty with a farther out `claim_expiration`.
### data bounties for `data_root` embedded shard block data
It would probably be valuable to be able to post data bounties that don't have the be the top level root in a shard block. This would require a merkle proof scheme be able to be submitted to `claim_bounty` rather than the assumption it's the top level root on the shard. One thing is we need to ensure that the `data_root` is not just trivially included as a leaf.
### Fewer on chain TXs
Can we remove `post_bounty` as an on-chain TX and instead just attach it to the `data_root` in the mempool? Maybe a cryptoeconomic commitment (slashing) or some sort of payment/state channel. The challenge with open-ended off-chain payments is that you can self-claim all the funds and so front-run everyone whom you claimed to pay. If we can't remove `post_bounty`, then the getting data on chain naively requires at least a 2 slot latency. Another thing to consider is slot staggering of execution shard(s) and data shards. That is, within a single slot, the bounty is posted on the execution shard then later in the slot, the data shard block is produced.