Each plasma chain MUST have at least one commitment contract. Commitment contracts hold the block headers for the plasma chain. Whenever the operator creates a new plasma block, they MUST publish this block to the commitment contract.
event BlockSubmitted( uint256 _number, bytes _header );
Emitted whenever a new block root has been published.
uint256: Block number that was published.
bytes: Header for that block.
Users need to know whenever a new block has been published so that they can stay in sync with the operator.
uint256 public currentBlock;
Block number of the most recently published plasma block.
Users need to know the current plasma block for various operations. Contract also needs to keep track of this so it knows what block is being published when
submitBlock is called.
mapping (uint256 => bytes) public blocks;
Mapping from block number to block header.
It’s often important to be able to pull a specific block header given a block number. This is necessary, for example, when verifying `inclusion proofs`_.
Other implementations often represent this mapping as
uint256 -> bytes32 under the assumption that the block header will always be a
bytes32 Merkle tree root. We instead represent the mapping as
uint256 -> bytes for more flexibility in the structure of the block root.
function submitBlock(bytes _header) public
Allows a user to submit a block with the given header.
bytes: Block header to publish.
It’s obviously necessary to expose some functionality that allows a user to submit a block header. However, the rationale around authentication logic is more interesting here.
Authentication in our original construction was handled by checking that msg.sender was the operator. This works well in a single-operator construction, but it doesn’t work if we wanted some more complex system. In order to solve this problem, we initinally wanted to add a
witness: bytes parameter to the method which could then be used to authenticate the submitted header. Fortunately, we stumbled on an even better solution.
Conveniently, if a contract calls another contract, then msg.sender within that second contract will be the address of the first contract. We can therefore outsource verification of a given block to some external contract and simply check that
msg.sender is that contract.
- SHOULD authenticate the block header in some manner.
- MUST increment
- MUST store the block header in
- MUST emit a