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 Transactionkeccak256 , 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 ⇒ bundleSizemapping(address => (mapping(uint => bytes))) public bundleHash
senderAddress ⇒ blockNumber ⇒ bundleHashmapping(address => (mapping uint => uint)) bundleIndexMap
senderAddress ⇒ blockNumber ⇒ bundleIndexbundleIndex 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 ⇒ verifiedverifyBundle() 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 whitelistbundleSize , bundleHash, inputted by the bundle sender is correct because bundle sender could game the system by randomly putting the arbitrary bundleSize and bundleHashtxs, 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 blockNumberbundleIndexMap 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 blockNumberblockNumber is the block when bundle was submittedsender by indexing the senderAddress.bundleSizeMap and bundleHashMap to get the bundleSize and bundleHash, given the senderAddress and blockNumberbundleHash 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

