Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(protocol): prove signal with full merkle proofs against block state roots #15683

Merged
merged 62 commits into from
Feb 11, 2024
Merged
Show file tree
Hide file tree
Changes from 58 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
ab12a57
breaking change by removing signal service overhead
dantaik Feb 5, 2024
3744fc8
Merge branch 'alpha-6' into alpha-7
dantaik Feb 5, 2024
b5728d1
Merge branch 'alpha-6' into alpha-7
dantaik Feb 6, 2024
a0f5efb
remove signalRoot step 1
dantaik Feb 7, 2024
019ef54
Update LibProving.sol
dantaik Feb 7, 2024
45e8ceb
more
dantaik Feb 7, 2024
9224460
Update LibUtils.sol
dantaik Feb 7, 2024
758ab07
Update LibVerifying.sol
dantaik Feb 7, 2024
71396f4
more
dantaik Feb 7, 2024
5aa18f5
Update TaikoL2.sol
dantaik Feb 7, 2024
b050af5
Update TaikoL2.sol
dantaik Feb 7, 2024
f978d83
Update TaikoL2.sol
dantaik Feb 7, 2024
7f48859
Make code compiling
Feb 7, 2024
ed3d47c
Add back helpers and uncomment lines
Feb 7, 2024
d6def2a
fix anchor
dantaik Feb 7, 2024
27de76a
Update TaikoL2.sol
dantaik Feb 7, 2024
05dd063
Update TaikoL2.t.sol
dantaik Feb 7, 2024
2e22f3e
minor
dantaik Feb 7, 2024
28134d6
rename
dantaik Feb 7, 2024
1e70e33
rename
dantaik Feb 7, 2024
425be15
update multi-hop bridging diagrams
dantaik Feb 7, 2024
7a2d7f2
more error messages in signal service
dantaik Feb 7, 2024
0a809f9
Update SignalService.sol
dantaik Feb 7, 2024
27f51d3
Update SignalService.sol
dantaik Feb 7, 2024
2bd445b
Update SignalService.sol
dantaik Feb 7, 2024
8200313
Update SignalService.sol
dantaik Feb 7, 2024
9ded143
comments
dantaik Feb 7, 2024
bef6290
Update LibVerifying.sol
dantaik Feb 7, 2024
c6e72ff
more
dantaik Feb 7, 2024
528288d
Update TaikoL2.sol
dantaik Feb 7, 2024
f8986e4
more
dantaik Feb 7, 2024
13e3f1f
more
dantaik Feb 7, 2024
70a26a4
remove unnecessary resolve
Feb 7, 2024
4ad3781
remove LibBlockHeader
dantaik Feb 8, 2024
5059135
Delete RLPWriter.sol
dantaik Feb 8, 2024
7ead006
Remove mint
dantaik Feb 8, 2024
dbd15c5
Merge branch 'alpha-7' into remove-signal-root
dantaik Feb 8, 2024
0821cad
Merge branch 'alpha-6' into alpha-7
dantaik Feb 8, 2024
8b5b97c
storageProof verification first trial
Feb 8, 2024
9f3c136
Merge branch 'alpha-6' into alpha-7
dantaik Feb 8, 2024
b86f7c5
Merge branch 'alpha-7' into remove-signal-root
dantaik Feb 8, 2024
77869c6
add old code to comparison
Feb 8, 2024
911c424
fix tests
dantaik Feb 8, 2024
92066ab
fix tests
dantaik Feb 8, 2024
7f6c74f
Fix account Merkle proof check
Brechtpd Feb 8, 2024
257d065
remove debug prints and rearrange tests
Feb 8, 2024
43c50f9
Always use SignalService from src chain as app addr
Feb 8, 2024
06ab25e
Merge branch 'remove-signal-root' into verify_full_merkle
adaki2004 Feb 8, 2024
3c208bf
remove comment
Feb 8, 2024
9ff8c05
Remove RLPWriter and some test comments
Brechtpd Feb 8, 2024
458234a
Merge branch 'main' into remove-signal-root
dantaik Feb 9, 2024
4f12970
Update TaikoToken.sol
dantaik Feb 9, 2024
67b9e4f
fix
dantaik Feb 9, 2024
0e70236
Merge branch 'remove-signal-root' into verify_full_merkle
dantaik Feb 9, 2024
182fe0a
pr comments
Feb 9, 2024
4511912
forge fmt
Feb 9, 2024
44c60fc
Merge branch 'main' into verify_full_merkle
adaki2004 Feb 10, 2024
a4c5439
resolve merge issues
Feb 10, 2024
8e1b3b2
custom error and rename function
Feb 11, 2024
e7a8c78
Merge branch 'main' into verify_full_merkle
dantaik Feb 11, 2024
3339164
Update GuardianVerifier.t.sol
dantaik Feb 11, 2024
73b88f0
fix(protocol): fix genesis test issue (#15738)
dantaik Feb 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions packages/protocol/contracts/libs/LibTrieProof.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: MIT
// _____ _ _ _ _
// |_ _|_ _(_) |_____ | | __ _| |__ ___
// | |/ _` | | / / _ \ | |__/ _` | '_ (_-<
// |_|\__,_|_|_\_\___/ |____\__,_|_.__/__/

pragma solidity ^0.8.24;

import { RLPReader } from "../thirdparty/optimism/rlp/RLPReader.sol";
import { SecureMerkleTrie } from "../thirdparty/optimism/trie/SecureMerkleTrie.sol";

/**
* @title LibTrieProof
*/
library LibTrieProof {
// The consensus format representing account is RLP encoded in the
// following order: nonce, balance, storageHash, codeHash.
uint256 private constant ACCOUNT_FIELD_INDEX_STORAGE_HASH = 2;

/**
* Verifies that the value of a slot in the storage of an account is value.
*
* @param stateRoot The merkle root of state tree.
* @param addr The address of contract.
* @param slot The slot in the contract.
* @param value The value to be verified.
* @param mkproof The proof obtained by encoding storage proof.
* @return verified The verification result.
*/
function verifyWithAccountProof(
bytes32 stateRoot,
address addr,
bytes32 slot,
bytes32 value,
bytes calldata mkproof
)
public
pure
returns (bool verified)
{
(bytes[] memory accountProof, bytes[] memory storageProof) =
abi.decode(mkproof, (bytes[], bytes[]));

bytes memory rlpAccount =
SecureMerkleTrie.get(abi.encodePacked(addr), accountProof, stateRoot);

require(rlpAccount.length != 0, "LTP:invalid account proof");

RLPReader.RLPItem[] memory accountState = RLPReader.readList(rlpAccount);

bytes memory storageRoot =
RLPReader.readBytes(accountState[ACCOUNT_FIELD_INDEX_STORAGE_HASH]);

verified = SecureMerkleTrie.verifyInclusionProof(
bytes.concat(slot), bytes.concat(value), storageProof, bytes32(storageRoot)
);
}
}
27 changes: 11 additions & 16 deletions packages/protocol/contracts/signal/SignalService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pragma solidity 0.8.24;
import "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol";
import "../common/EssentialContract.sol";
import "../common/ICrossChainSync.sol";
import "../libs/LibTrieProof.sol";
import "../thirdparty/optimism/trie/SecureMerkleTrie.sol";
import "../thirdparty/optimism/rlp/RLPReader.sol";
import "./IHopRelayRegistry.sol";
Expand Down Expand Up @@ -57,6 +58,7 @@ contract SignalService is EssentialContract, ISignalService {
error SS_INVALID_PARAMS();
error SS_INVALID_PROOF();
error SS_INVALID_APP();
error SS_INVALID_HOP_PROOF();
error SS_INVALID_RELAY();
error SS_INVALID_SIGNAL();
error SS_INVALID_STATE_ROOT();
Expand Down Expand Up @@ -121,6 +123,9 @@ contract SignalService is EssentialContract, ISignalService {
hrr = IHopRelayRegistry(resolve("hop_relay_registry", false));
}

ICrossChainSync ccs = ICrossChainSync(resolve("taiko", false));
bytes32 stateRoot = ccs.getSyncedSnippet(p.height).stateRoot;

// If a signal is sent from chainA -> chainB -> chainC (this chain), we verify the proofs in
// the following order:
// 1. using chainC's latest parent's stateRoot to verify that chainB's TaikoL1/TaikoL2
Expand All @@ -131,6 +136,7 @@ contract SignalService is EssentialContract, ISignalService {
// We always verify the proofs in the reversed order (top to bottom).
for (uint256 i; i < p.hops.length; ++i) {
Hop memory hop = p.hops[i];
if (hop.stateRoot == stateRoot) revert SS_INVALID_HOP_PROOF();

if (!hrr.isRelayRegistered(_srcChainId, hop.chainId, hop.relay)) {
revert SS_INVALID_RELAY();
Expand All @@ -143,9 +149,6 @@ contract SignalService is EssentialContract, ISignalService {
_srcSignal = hop.stateRoot;
}

ICrossChainSync ccs = ICrossChainSync(resolve("taiko", false));
bytes32 stateRoot = ccs.getSyncedSnippet(p.height).stateRoot;

verifyMerkleProof(stateRoot, _srcChainId, _srcApp, _srcSignal, p.merkleProof);
return true;
}
Expand All @@ -164,9 +167,12 @@ contract SignalService is EssentialContract, ISignalService {
if (stateRoot == 0) revert SS_INVALID_STATE_ROOT();
if (merkleProof.length == 0) revert SS_INVALID_PROOF();

bool verified;
address signalService = resolve(srcChainId, "signal_service", false);

// TODO(dani): implement this please
bytes32 slot = getSignalSlot(srcChainId, srcApp, srcSignal);
bool verified = LibTrieProof.verifyWithAccountProof(
stateRoot, signalService, slot, hex"01", merkleProof
);

if (!verified) revert SS_INVALID_PROOF();
}
Expand Down Expand Up @@ -201,17 +207,6 @@ contract SignalService is EssentialContract, ISignalService {
return false;
}

/// @notice Translate a RLP-encoded list of RLP-encoded TrieNodes into a list of LP-encoded
/// TrieNodes.
function _transcode(bytes memory proof) internal pure returns (bytes[] memory proofs) {
RLPReader.RLPItem[] memory nodes = RLPReader.readList(proof);
proofs = new bytes[](nodes.length);

for (uint256 i; i < nodes.length; ++i) {
proofs[i] = RLPReader.readBytes(nodes[i]);
}
}

function _authorizePause(address) internal pure override {
revert SS_UNSUPPORTED();
}
Expand Down
63 changes: 63 additions & 0 deletions packages/protocol/test/libs/LibTrieProof.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import "../TaikoTest.sol";
import "../../contracts/libs/LibTrieProof.sol";

contract TestVerifyWithAccountProof is TaikoTest {
function test_verifyWithAccountProof() public {
// Not needed for now, but leave it as is.
//uint64 chainId = 11_155_111; // Created the proofs on a deployed Sepolia
// contract, this is why this chainId.
// Actually this is the messageHash i sent (obviously just a made up bytes32!)
// Not needed for now, but leave it as is.
//bytes32 signalSent = 0x21761f7cd1af3972774272b39a0f4602dbcd418325cddb14e156b4bb073d52a8;
// //Actually a messageHash
// This one is the "sender app" aka the source bridge but i mocked it for now to be an EOA
// (for slot calculation)
address contractWhichStoresValue1AtSlot = 0x17DF3c450D1dC61558ecA7B10e4bBC8ddcdB1f28;
// This is the slot i queried the eth_getProof on Sepolia for blockheight: 0x5000B5
bytes32 slotStoredAtTheApp =
0xfa2ef1bab164a0522c2c110bbea1a54ac6399d3ba24437480c29947143a5402e;
// This is the worldStateRoot at blockheight: 0x5000B5 (Sepolia!)
bytes32 worldStateRoot = 0x90c5f343ed98545ad5ad4e840492e1008218c0ea92f8fd74a826aaf4c477a3fe;
// This is the worldStateRoot just RLP encoded with
// https://toolkit.abdk.consulting/ethereum#key-to-address,rlp
// Not needed for now but leave it as is
//bytes memory worldStateRootRLPEncoded =
// hex"e1a090c5f343ed98545ad5ad4e840492e1008218c0ea92f8fd74a826aaf4c477a3fe";

bytes[] memory accountProof = new bytes[](8);
// eth_getProof responds some bytes
accountProof[0] =
hex"f90211a01564179a33d2ff80c3618ab74314aad556cb7652c2d51f7a3aff3a787ecdb29ea03bd6509773c4530091e420ef4921beef2be63ad2429b6e12ba5d7a7f9a6da270a090be43dc028d9eb13a63b5799782f30928e6882b328ab845f320e1eb138d7962a026633ae06c23cd30c5e1cc91cfd7be03652cb9c853fa42538803c8eb631e920fa0711616cf812d7ed5f308b2822bffc5038edac8abedb0f7339c9933387472b495a09266ec8cec3b85e1ea194e79c73a4b2ecc122abffa356b575c31af7e9d3b6921a0a16f884fe19eeaefb8eeb2f017f6ecb24ee5822d5b3bc4be98bcfe374a910761a07973653d008e00cebcc3794f8221fa530d9a18ce77331a3e473e8dc3735943d9a0bc31a4cd1ab5c4ff0bd12f6ffc12f5ef19897df9addc478aa06b223d3087ef9da059aec5d8753109a5893d67ec742b2b51703ecf5920e4947007a6c77265ac41f9a09c0af28e7444278ab0b478870fa98c9f37e9d19681023f8e039f3ce67492e707a008395a6c64c1c76a1e655a28419504519e9957251e83501eef6093971f937c19a04f2a4e14fe7bbf05ea2b75de2bfe95fd33d2c86ff554293ebdf09da7da579cd5a0816ed8d0b69fce577f3c70eceebe8634387716d91a1edc4b3cc9d5feea31ba94a0a270d82ecded0d0712336be6e078794e533721b40698c9b5165b6c420a8a8545a0bcfbc71cc6ee796c58ef28f0d0e453fc08f6326c1891b51512e19af5f4842ffe80";
accountProof[1] =
hex"f90211a0c441ffc1fe3662f328ca995e9cad90cecf26ad98028846b7a1bdb6fe60aa8419a058336ba27c2e0feb5bd8bdeea62ebe54fc4cc05e2376f69e1c721b1cd9098498a07b847e55c107bd976b5984ea7d97d39c68573ae74afd82d4ab9d857cb44e6f82a05f5c1810a0178191798266d171f2f9f9711f5116c5dc4ecccbc29642a24b1873a01da99f321b183e1a2068ac0fd57dccbd637b3fa91b060a80c836ce1ea79fcae0a0f8cf0f8299146bf9d1ec0b8932ddc23ec29cd61daf5cdbe704a5c90f31f0d60ca0407441445132919ff986f169f24e82ce53fe15a444a674ab1604f0924efdd51da0313be5d2f630a30f414aed4012bbe081e55853a55209a3a83045b62f10d74ad2a0ab4a1665cc9ac1dc2f87d98c55e9b893acf84e592635d359a83d0e14181a933da0e4ed4ac12b93b12016ae1c0fd62e6a15b01e617779e8611c27ce22b0b5e78d68a0852127e581d41ec5c58d6a5ccb1b0e7ae90553575b0d9ffb2ac847515671c80fa01ec12bc1938419bebfdc17ed6d10d456fe31202f2dd1534e9bc6b78c95e2b358a000e5a67fdc3cc307a3244b77ddb504867a2cfb0cc9a614a47452d8cfad011af4a0a222a375f0b35461137d84e1beb8cc0e842ea7194784286b0426d80e04ce0ee6a04dc890b4343e041888128a5185860e039b82636d328c52f630007339d445fc0aa00619a2c3c30245bef0821c9f85bc3b79ee2b7f895a4de79ad57f42add8f8cc8d80";
accountProof[2] =
hex"f90211a02b8838e8f55f133d202a53a8b8d9243d936f43b636e8edf4cead5028150ba4bda0199e1c6b8025bdb25824acf47c79f2cb46e9912eea4c7951b1841e6831361cf7a03f9cf217c04256b4b8d32218e998e34a2bb16c17aec758811d9cf2b2510a50a0a06a04facdefe440e0d78718bee9ac31d6693d197ea44bb324156d3bcbdc601763a0d30849e23529944c1763e9de2d3ae6d229b4310bcb2415dec58e5375d04d23efa0a4013ee6afb6af932f3e2d126fbe53f656be59f27df7c700099c91e2a65e2bd3a0233ef3fbc0234cbcb9f76ad4ece6c2f50e480e873226f8f8cef2851d10a7ee33a0b5d1dc30ea1bad8ac548ffd9ac408eabb033f2fcf8d3c1780da97180d89f5997a0a4192803a6131538e307b331f9f842b2302d17492f37537a56a63c36eb01b408a06087dc2726b6a21a4d06d7d73b988925cf3ba2c898d442024468a52f8a4010a8a0bfa291361ed2810c2f8ab0eee7fd894e5915e8ad2d12739d4f380466dc3c7f55a08becd8c73f80d6073df6cceb89e796e669744aa852ce13c7b367fe60c2b34d04a012c2d1a15f1bf98ad00cd0eb061a42eaaf0015a5f4c41a894f249c9a3afc3560a0fef566b4ad9fa37ee9ae59f880f4bb38958c8a62f26ae3668f1dbda3e9fd3b05a0702301629db7bdddcc00dbd348adbcffc890bb1c80fe6ef7a996363adc89770da068b975b9b36fc59378c54d5dd868e53ea8a59248da1dc6c4576d9f781913cd7880";
accountProof[3] =
hex"f90211a0d98672296e62b8aba7e20671ca0476e58efc4ad0c40480e9ced84696bbfa56a8a0d2c53384b6e3b1b3088fcd412af98f85a52b882914a35adb2aa56cd3484997ada09015daa671fe301f656b0ed4f4f2172d683dae40113979a3f710145106031767a00d055b96c4f5804b7d3e4b8159d72bd84ca9e8b4547b504fe2a9933b4359a2d4a0d2560c909a3b2cc465480d1815b06c613d7a2ae7f6c1f00027cf4a57cdc282d7a0c29b7764bdd0df90b1fe350b488ffe69c3c4202f1712c77aab4fa2e0103ae673a06ca16b3f2b111bb14b8b52d36b85b7df2dada9796c2dd0b13f293149cb3e38fba0219ab02566d6474fa0621669616f97f7be79e1cb5886bc75be99be4984bd978ca0d103757173ada974a0f4996e3191ebce8f3ddc61c9db536ff7389c010b03e536a0f65268a6de255bde8ea97282e9f7a858b15b5bde5b9cde5b654c19cd909231f8a06c3ee37ad1762f6fb9da2b3efec779a61036f76b4c97b3ba8ea1339cfc76393ea09b28c2f98e0eedafa97d733d468c1d7a505f8d6b544bbbaf990cdd4781ee765ea0eeda6a2e3dd383ab103d9c14656df77a6b05a566338745325edb03ab344c7404a0ca35c2b85039e6a1fce323649d015876c13702faa510cee4f4a7efaac5456185a00a0e83158f3c174485b6b6ff64f793d0bd578215a685acc86b002bcc99c99f9ba0fd0d0c3d0f27d3e7bc63462df509157e56d03e310ee26a60a4f7dfa87a9e0c2080";
accountProof[4] =
hex"f90211a0f69c09b524b3e7a97fe238809583b7b68f41443a76c0f5d689b371c1df513fc1a0d0f0bcbbd6dae7bd8dd9ba196a34e81c7cc9fea6ac4894a69ec2b5b7bdae2f01a081975fbe995c9a7a55b8e846a70be0d6695c8529b7f564448bf64f2ef25d8c5ca02cd43f9e6fafbe13cc8e845d8c19b51ddc62610119948c635c7e1c9c9998dc22a03b4e6dfe0edcdfbb0b8252f97cc6d2a11f25c571b093cc53aca88d38a94bf827a0e9b70cbde13f142578dba52a5a862122a2332e15c148edda2b9b419528ee9231a014ff7fc46869c016d4ac3b0487a59bf269a4d80fd1afce355f5343d8135bcadaa0d65fafd2a1e02154fcf48c51a354ab294799c6c0444bfadc792ea195e9b9fdefa0edfde20b547f393f4c05f1e6e32b10da328df10d0b231b5c5af4f0d02bdd3492a095fd7a02b5be79308c127233cec06c203ae54ed2c85b69878eeb13abfc9d6a9aa0af6751551d96ea25ae9afb6113a2c13bef56254c3ea24b1a643562fdbdb4100da0c3b3d7526009039e7cf06279d8226f536ccedbed96da7d3f82aa878063bbeb9aa03dcfed22cae1cee772be285fbba92960fe887eb0997eb9a221849e690b2a6917a05c86e58c113f61d4c44bbe0d6c45ee4d4cdf1ecf308d1f0d43f2a284e0bd1300a03eea9d225bd25dc3dc2d48bf156abc17e6d20686624fa5e93ab8b05f42058e34a0794f702cf0ca4e67ad88a9e9ee7d51adf3b3b3aa47621aa5bf0b8cab433176ec80";
accountProof[5] =
hex"f901f1a0605770c9b68c1b4e33579a35850c1c44731852d55172ec379b2377e54c359d9ca0d704783a3e1d333129d0305964be5f1af602b860253deddb80c0b36bb71f697ca0b4c43f62e620af02dbeaf9d0e79b62d30041ef97ceb70190e3a1bfa0711ddd21a0ffc993b4e33b8a39b84563804f7439299ca8cc0ce747625fb160baccaac0ae56a073146beddea840ed57473fa066835ba3f5b4a7a950965aa8b97b55604ad328e280a0461d8ad7f395cfca01b2b5173ac2cbc81f0343061a4cad2d93593b29d91ba9baa067a777686549c4b2408aa78e935a777bc447b5055a778faf62a5dda63f5c274ea0903c36605f0616a74dcbb4730437ffefea698cbef452e19a08072830f25c581fa06ff86e3168eb6b77472acb077d925fd36000139a924531125a1cd469152712d2a048fd7f01074966c50c0a3cc68a53a0ea29410c0f9a37595657493ec9dffcd4e9a02358f5f4c8b91b0b865a8f70f22f9f082aefeccd53776ba835ead842ff9d74a0a03f7d16b8024d3f8cd006b4e6cc69ce07c520178254ebafe68ada722871342257a08e1bf934b22c0a817fb470fb0e8c792fd1987f062a1af318de783df5a9c71081a063d0b5247f4a977839a12223db8c2e6f120ea6f0db673f0fb056415745e8015ba0cca532f0172104741733687ad1b87337f554def14726f29fabc556b070d077cf80";
accountProof[6] =
hex"f8518080808080808080808080a04fc082a60fe2f12e75c8d6dddca59133c0e855e7d412ffbaba8c2117d37aa35780a06bd1536769280b725a364161ed10f1737f8b70938227ae1cdda228f45ac1e168808080";
accountProof[7] =
hex"f8669d3a74f1d0cadee872fd4b113921a69b6f137711ffc6bc55289ddac192dcb846f8440180a0f7916f389ccda56e3831e115238b7389b30750886785a3c21265601572698f0fa040ed175bbf1e21348615151831ea7a1164fb6d1bd4e1fa03290f0d97bd122021";

bytes[] memory storageProof = new bytes[](1);
storageProof[0] =
hex"e3a1209749684f52b5c0717a7ca78127fb56043d637d81763c04e9d30ba4d4746d56e901";
bytes memory merkleProof = abi.encode(accountProof, storageProof);

vm.startPrank(Alice);
LibTrieProof.verifyWithAccountProof(
worldStateRoot,
contractWhichStoresValue1AtSlot,
slotStoredAtTheApp,
hex"01",
merkleProof
);
}
}
2 changes: 1 addition & 1 deletion packages/protocol/test/verifiers/GuardianVerifier.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ contract TestGuardianVerifier is TaikoL1TestBase {
}

// Tests `verifyProof()` with the wrong prover
function test_verifyProof_invalidProver() public {
function test_verifyProof_invalidProver() public {
// Context
IVerifier.Context memory ctx = IVerifier.Context({
metaHash: bytes32(0),
Expand Down
Loading