Proof of Bundle Integrity allows bundle senders to express exact slot he/she wants his/her bundle to be placed on a block and trustlessly prove whether a block builder has tempered with the bundle leveraging zero knowledge proof
There will be only one contract, call it proofOfIntegrity.sol
When new bundle is submitted, a sender should include a tx calling the stamp()
function of the proofOfIntegrity.sol
contract
stamp(Txs tx, uint blockNumber, uint bundleIndex)
Txs
is an array that takes in a contract defined Transaction
type i.e. struct Transaction
keccak256
, count the tx number in the bundle, and use blockNumber
and msg.sender
to update to mappings
mapping(address => (mapping(uint = > uint))) public bundleSizeMap
senderAddress
⇒ blockNumber
⇒ bundleSize
mapping(address => (mapping(uint => bytes))) public bundleHash
senderAddress
⇒ blockNumber
⇒ bundleHash
mapping(address => (mapping uint => uint)) bundleIndexMap
senderAddress
⇒ blockNumber
⇒ bundleIndex
bundleIndex
is to express the slot number a bundle wants to be placed in the block. The top slot a bundle can express is 2, since the slot 1 will always be taken by the verifyBundle()
function invoked by the block builder(more on this later)mapping(address => (mapping uint => bool)) bundleVerificationMap
. If the ending bool
is the default value 0
, then the function reverts with log bundleVerificationMap not updated
verifyBundle()
transaction call on the top of the bundle. This will also let the block builder know that the sender has requested that he/she wants the bundle to be later subject to proof-of-integritysenderAddress
⇒ blockNumber
⇒ verified
verifyBundle()
function(more on this in the following section)when the bundle is submitted, the block builder needs to call the verifyBundle()
function, and this function can only be called by a whitelisted block builders in a whitelist
mapping
verifyBundle(Txs txs, address sender, uint blockNumber) onlyBlockBuilder returns(bundleIndex)
onlyBlockBuilder
is a modifier checking whether the caller is in the whitelist
bundleSize
, bundleHash
, inputted by the bundle sender is correct because bundle sender could game the system by randomly putting the arbitrary bundleSize
and bundleHash
txs
, sender
, blockNumber
. All three of these values can be found the in the bundle submitted by the bundle sendertxs
, and use sender
and blockNumber
to query the bundleSizeMap
. If match, continue; otherwise revertbundleHash
from the txs
, and use sender
and blockNumber
to query the bundleHashMap
. if match, continue; otherwise revertbundleVerificationMap
to true by providing the sender
and blockNumber
bundleIndexMap
to get the index a bundle sender wantsverifyBundle()
on the top of the bundle, to the block. Otherwise, the block builder discard the bundle.
verifyBundle()
can be called in a simulation to get the bundleIndexMap
💡 Technically, a block builder can still temper the bundle after this step. A malicious block builder could call the verifyBundle()
function first, then to change the ordering, or insert its own transaction in the middle of the bundle, and include the tempered bundle into the block. All of the previous steps are for a block builder to verify the arguments supplied by the bundle sender in stamp()
function is correct.
This is why we need the following steps
After the block has been built and mined on-chain. A third party could challenge by submitting a proof of integrity using Axiom V2
In a challenge, a user could use a front-end application to query two values leveraging Axiom V2
senderAddress
and blockNumber
blockNumber
is the block when bundle was submittedsender
by indexing the senderAddress
.bundleSizeMap
and bundleHashMap
to get the bundleSize
and bundleHash
, given the senderAddress
and blockNumber
bundleHash
value in the browser. If it matches the bundleHash
result from the Axiom V2 API, then it mean bundle was not tempered with; otherwise, it means the bundle has been temperedbundleIndex
to see if the block builder actually put the bundle at the slot number a bundle sender requested in the stamp()
functionIt's made using Axiom's V2 to trustlessly prove the behavior of a block builder. Front-end is generated using Axiom V2's repl export feature. Additionally, a mock block builder to test the mechanism has also been provided.
The mechanism works mostly by allowing sender and blockbuilder respectively insert transactions at the bottom and top of a bundle