From b7c5b6d2fa4576f86f67360ad6e59d0b1824d6b6 Mon Sep 17 00:00:00 2001 From: Marcos Nicolau Date: Mon, 22 Dec 2025 16:58:14 -0300 Subject: [PATCH 1/2] feat: move sdk from crates dir to aggregation mode dir --- aggregation_mode/Cargo.lock | 3 + aggregation_mode/Cargo.toml | 1 + aggregation_mode/proof_aggregator/Cargo.toml | 2 +- aggregation_mode/sdk/Cargo.toml | 7 +- .../abi/AlignedProofAggregationService.json | 1 + aggregation_mode/sdk/src/beacon.rs | 154 +++++++++++++ .../sdk/src/blockchain/helpers.rs | 34 +++ aggregation_mode/sdk/src/blockchain/mod.rs | 9 + .../sdk/src/blockchain/provider.rs | 186 +++++++++++++++ aggregation_mode/sdk/src/blockchain/types.rs | 211 ++++++++++++++++++ aggregation_mode/sdk/src/lib.rs | 3 +- aggregation_mode/sdk/src/types.rs | 6 + 12 files changed, 613 insertions(+), 4 deletions(-) create mode 100644 aggregation_mode/sdk/abi/AlignedProofAggregationService.json create mode 100644 aggregation_mode/sdk/src/beacon.rs create mode 100644 aggregation_mode/sdk/src/blockchain/helpers.rs create mode 100644 aggregation_mode/sdk/src/blockchain/mod.rs create mode 100644 aggregation_mode/sdk/src/blockchain/provider.rs create mode 100644 aggregation_mode/sdk/src/blockchain/types.rs diff --git a/aggregation_mode/Cargo.lock b/aggregation_mode/Cargo.lock index 6e424297a..3ec59f7e6 100644 --- a/aggregation_mode/Cargo.lock +++ b/aggregation_mode/Cargo.lock @@ -307,8 +307,11 @@ version = "0.1.0" dependencies = [ "alloy", "bincode", + "lambdaworks-crypto", "reqwest 0.12.24", "serde", + "serde_json", + "sha3 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", "sp1-sdk", "tokio", "tracing", diff --git a/aggregation_mode/Cargo.toml b/aggregation_mode/Cargo.toml index 2ab51157c..b8b738414 100644 --- a/aggregation_mode/Cargo.toml +++ b/aggregation_mode/Cargo.toml @@ -11,6 +11,7 @@ serde = { version = "1.0.203", features = ["derive"] } serde_json = "1.0.117" serde_yaml = "0.9" alloy = { version = "1.1.1", features = ["default", "signer-keystore", "kzg"] } +lambdaworks-crypto = { git = "https://github.com/lambdaclass/lambdaworks.git", rev = "5f8f2cfcc8a1a22f77e8dff2d581f1166eefb80b", features = ["serde"]} bincode = "1.3.3" aligned-sdk = { path = "../crates/sdk/" } db = { path = "./db" } diff --git a/aggregation_mode/proof_aggregator/Cargo.toml b/aggregation_mode/proof_aggregator/Cargo.toml index 2c367a144..17d3f3965 100644 --- a/aggregation_mode/proof_aggregator/Cargo.toml +++ b/aggregation_mode/proof_aggregator/Cargo.toml @@ -19,7 +19,7 @@ tokio = { version = "1", features = ["time"]} sha3 = "0.10.8" reqwest = { version = "0.12" } ciborium = "=0.2.2" -lambdaworks-crypto = { git = "https://github.com/lambdaclass/lambdaworks.git", rev = "5f8f2cfcc8a1a22f77e8dff2d581f1166eefb80b", features = ["serde"]} +lambdaworks-crypto = { workspace = true } rayon = "1.10.0" backon = "1.2.0" sqlx = { version = "0.8", features = [ "runtime-tokio", "postgres", "uuid", "bigdecimal" ] } diff --git a/aggregation_mode/sdk/Cargo.toml b/aggregation_mode/sdk/Cargo.toml index 3e8a92408..eeb5cb1f4 100644 --- a/aggregation_mode/sdk/Cargo.toml +++ b/aggregation_mode/sdk/Cargo.toml @@ -5,10 +5,13 @@ edition = "2021" [dependencies] serde = { workspace = true } +serde_json = { workspace = true } +alloy = { workspace = true } +sp1-sdk = { workspace = true } +lambdaworks-crypto = { workspace = true } tracing = { version = "0.1", features = ["log"] } tracing-subscriber = { version = "0.3.0", features = ["env-filter"] } bincode = "1.3.3" reqwest = { version = "0.12", features = ["json", "multipart"] } tokio = { version = "1", features = ["time"]} -alloy = { workspace = true } -sp1-sdk = { workspace = true } +sha3 = { version = "0.10.8" } diff --git a/aggregation_mode/sdk/abi/AlignedProofAggregationService.json b/aggregation_mode/sdk/abi/AlignedProofAggregationService.json new file mode 100644 index 000000000..813d0291a --- /dev/null +++ b/aggregation_mode/sdk/abi/AlignedProofAggregationService.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"RISC0_ID","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"SP1_ID","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"VERIFIER_MOCK_ADDRESS","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"alignedAggregatorAddress","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"allowVerifyingProgram","inputs":[{"name":"verifierProgramCommitment","type":"bytes32","internalType":"bytes32"},{"name":"provingSystemId","type":"uint8","internalType":"uint8"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"allowedVerifiersProvingSystem","inputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"disallowVerifyingProgram","inputs":[{"name":"verifierProgramCommitment","type":"bytes32","internalType":"bytes32"},{"name":"provingSystemId","type":"uint8","internalType":"uint8"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"initialize","inputs":[{"name":"newOwner","type":"address","internalType":"address"},{"name":"_alignedAggregatorAddress","type":"address","internalType":"address"},{"name":"_sp1VerifierAddress","type":"address","internalType":"address"},{"name":"_risc0VerifierAddress","type":"address","internalType":"address"},{"name":"_risc0AggregatorProgramImageId","type":"bytes32","internalType":"bytes32"},{"name":"_sp1AggregatorProgramVKHash","type":"bytes32","internalType":"bytes32"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isMerkleRootVerified","inputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isProofVerified","inputs":[{"name":"merklePath","type":"bytes32[]","internalType":"bytes32[]"},{"name":"provingSystemId","type":"uint16","internalType":"uint16"},{"name":"programCommitment","type":"bytes32","internalType":"bytes32"},{"name":"publicInputs","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"proxiableUUID","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"risc0VerifierAddress","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"setRisc0VerifierAddress","inputs":[{"name":"_risc0VerifierAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setSP1VerifierAddress","inputs":[{"name":"_sp1VerifierAddress","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"sp1VerifierAddress","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"upgradeTo","inputs":[{"name":"newImplementation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"upgradeToAndCall","inputs":[{"name":"newImplementation","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"verifyAggregationRisc0","inputs":[{"name":"blobVersionedHash","type":"bytes32","internalType":"bytes32"},{"name":"risc0ReceiptSeal","type":"bytes","internalType":"bytes"},{"name":"risc0JournalBytes","type":"bytes","internalType":"bytes"},{"name":"verifierProgramCommitment","type":"bytes32","internalType":"bytes32"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"verifyAggregationSP1","inputs":[{"name":"blobVersionedHash","type":"bytes32","internalType":"bytes32"},{"name":"sp1PublicValues","type":"bytes","internalType":"bytes"},{"name":"sp1ProofBytes","type":"bytes","internalType":"bytes"},{"name":"verifierProgramCommitment","type":"bytes32","internalType":"bytes32"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"AdminChanged","inputs":[{"name":"previousAdmin","type":"address","indexed":false,"internalType":"address"},{"name":"newAdmin","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"AggregatedProofVerified","inputs":[{"name":"merkleRoot","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"blobVersionedHash","type":"bytes32","indexed":false,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"BeaconUpgraded","inputs":[{"name":"beacon","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint8","indexed":false,"internalType":"uint8"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Risc0VerifierAddressUpdated","inputs":[{"name":"newAddress","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"SP1VerifierAddressUpdated","inputs":[{"name":"newAddress","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Upgraded","inputs":[{"name":"implementation","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"VerifierProgramAllowed","inputs":[{"name":"verifierProgramCommitment","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"provingSystemId","type":"uint8","indexed":false,"internalType":"uint8"}],"anonymous":false},{"type":"event","name":"VerifierProgramDisallowed","inputs":[{"name":"verifierProgramCommitment","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"provingSystemId","type":"uint8","indexed":false,"internalType":"uint8"}],"anonymous":false},{"type":"error","name":"InvalidProvingSystemId","inputs":[{"name":"actual","type":"uint8","internalType":"uint8"}]},{"type":"error","name":"InvalidVerifyingProgram","inputs":[{"name":"verifierProgramCommitment","type":"bytes32","internalType":"bytes32"},{"name":"expected","type":"uint8","internalType":"uint8"},{"name":"actual","type":"uint8","internalType":"uint8"}]},{"type":"error","name":"OnlyAlignedAggregator","inputs":[{"name":"sender","type":"address","internalType":"address"}]},{"type":"error","name":"ProvingSystemIdMismatch","inputs":[{"name":"expected","type":"uint8","internalType":"uint8"},{"name":"received","type":"uint8","internalType":"uint8"}]}],"bytecode":{"object":"0x60a080604052346100da57306080525f549060ff8260081c16610088575060ff8082161061004e575b6040516116cc90816100df82396080518181816109a401528181610aca0152610f8e0152f35b60ff90811916175f557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160ff8152a15f610028565b62461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b6064820152608490fd5b5f80fdfe6080806040526004361015610012575f80fd5b5f905f3560e01c908163294e3ccb1461126e575080633659cfe614610f7057806339ad96d914610e1757806342af056814610dea5780634c46688c14610dc15780634f1ef28614610a5457806352d1902d1461099157806355a9a7bf146108e8578063616af4f7146108bf5780636eecb4c9146108a3578063715018a61461084657806383501b211461082a5780638da5cb5b14610801578063972e58ba146107e557806398dc5b03146107b65780639eade0f11461074e578063a52f681b146106e6578063be96ce9314610563578063d5d8d0a8146104d8578063e03e3691146103ae578063f28c3e37146101a35763f2fde38b14610110575f80fd5b346101a05760203660031901126101a057610129611291565b610131611484565b6001600160a01b0381161561014c57610149906114dc565b80f35b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b80fd5b50346101a05760c03660031901126101a0576101bd611291565b6024356001600160a01b038116908190036103aa576044356001600160a01b038116908190036103a6576064356001600160a01b03811692908390036103a257845460ff8160081c161594858096610395575b801561037e575b156103225760ff19821660011787556102689186610311575b5061024a60ff885460081c1661024581611524565b611524565b610253336114dc565b61026360ff885460081c16611524565b6114dc565b6001600160601b0360a01b60cb54161760cb556001600160601b0360a01b60ca54161760ca556001600160601b0360a01b60cc54161760cc55608435825260cd60205260408220600260ff1982541617905560a435825260cd60205260408220600160ff198254161790556102da5780f35b61ff001981541681557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160018152a180f35b61ffff19166101011787555f610230565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b50303b1580156102175750600160ff831614610217565b50600160ff831610610210565b8480fd5b8380fd5b8280fd5b50346101a05760803660031901126101a05760043567ffffffffffffffff81116104d457366023820112156104d45780600401359067ffffffffffffffff82116103aa573660248360051b830101116103aa5760243561ffff811681036103a65760643567ffffffffffffffff81116103a25761047161043460429236906004016112a7565b929083604051948592602084019761ffff60f01b9060f01b168852604435602285015284840137810188838201520301601f198101835282611330565b5190209083915b838310156104b95760248360051b83010135908181105f146104a85785526020526001604085205b920191610478565b9085526020526001604085206104a0565b60ff604086602093815260c984522054166040519015158152f35b5080fd5b50346101a05760ff6104e936611382565b6104f4929192611484565b16600181141580610558575b6105465760207e86b661a41d941418d5d36446dc66bee8596027431ea48aba1cdbf9ab8cbada9183855260cd8252604085208160ff19825416179055604051908152a280f35b633212f51f60e21b8352600452602482fd5b506002811415610500565b50346101a057610572366112d5565b60cb5492959493929091906001600160a01b031633036106d35760208682810103126106cf5785359582885260cd602052600260ff60408a205416036106a3578782602092829796959460405192839283378101838152039060025afa156106985783519260018060a01b0360cc541690813b15610694578593610615936040519687958694859463ab750e7560e01b8652606060048701526064860191611464565b916024840152604483015203915afa801561068957610674575b507ffe3e9e971000ab9c80c7e06aba2933aae5419d0e44693e3046913e9e58053f6291836020925260c9825260408520600160ff19825416179055604051908152a280f35b8161067e91611330565b6103aa57825f61062f565b6040513d84823e3d90fd5b8580fd5b6040513d85823e3d90fd5b82885260cd6020526040882054635a08a53760e01b89526004849052600260245260ff16604452606488fd5b5f80fd5b63921f325560e01b875233600452602487fd5b50346101a05760203660031901126101a057610700611291565b610708611484565b60cc80546001600160a01b0319166001600160a01b039290921691821790557f80ad03c31df486a2ab8f2fe1f9e0597e290255e749369a3e0cf3b1cf34b180898280a280f35b50346101a05760203660031901126101a057610768611291565b610770611484565b60ca80546001600160a01b0319166001600160a01b039290921691821790557fc34d8b9ef5ec2845c44a69730b4523b5d66bc715b6d4820707ff1f40ee5f1a9e8280a280f35b50346101a05760203660031901126101a05760ff6040602092600435815260c984522054166040519015158152f35b50346101a057806003193601126101a057602060405160028152f35b50346101a057806003193601126101a0576033546040516001600160a01b039091168152602090f35b50346101a057806003193601126101a057602060405160ff8152f35b50346101a057806003193601126101a05761085f611484565b603380546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346101a057806003193601126101a057602060405160018152f35b50346101a057806003193601126101a05760cc546040516001600160a01b039091168152602090f35b50346101a05760ff6108f936611382565b610904929192611484565b16600181141580610986575b6105465781835260cd60205260ff6040842054169080820361096e575060207fca6a89a45ac13d034743c006df767832823ffba941ccc74cca0cb5dcd0abffaf9183855260cd82526040852060ff198154169055604051908152a280f35b63d4cec2bb60e01b8452600491909152602452604482fd5b506002811415610910565b50346101a057806003193601126101a0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031630036109e95760206040515f5160206116775f395f51905f528152f35b60405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608490fd5b5060403660031901126101a057610a69611291565b60243567ffffffffffffffff81116103aa57366023820112156103aa5780600401359083610a9683611366565b91610aa46040519384611330565b838352602083019336602482840101116103aa5780602460209301863783010152610b1c7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610afe308214156113a2565b5f5160206116775f395f51905f52546001600160a01b031614611403565b610b24611484565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610b5957505061014990611584565b6040516352d1902d60e01b81526001600160a01b03841690602081600481855afa869181610d89575b50610be35760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608490fd5b5f5160206116775f395f51905f5203610d3257610bff84611584565b604051907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8680a2815115801590610d2a575b610c3e575b5050505080f35b833b15610cd95750610cc8928492839251915af43d15610cd2573d610c6281611366565b90610c706040519283611330565b81523d84602083013e5b60405191610c89606084611330565b602783527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6020840152660819985a5b195960ca1b604084015261161b565b505f808080610c37565b6060610c7a565b62461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608490fd5b506001610c32565b60405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608490fd5b9091506020813d602011610db9575b81610da560209383611330565b81010312610db55751905f610b82565b8680fd5b3d9150610d98565b50346101a057806003193601126101a05760cb546040516001600160a01b039091168152602090f35b50346101a05760203660031901126101a05760ff6040602092600435815260cd8452205416604051908152f35b50346106cf57610e26366112d5565b60cb5493959491936001600160a01b03163303610f5d5760208287810103126106cf57813595815f5260cd602052600160ff60405f20541603610f315760ca546001600160a01b031691823b156106cf57610ebc5f95610eaa976040519889978896879663020a49e360e51b88526004880152606060248801526064870191611464565b84810360031901604486015291611464565b03915afa8015610f2657610f10575b5060207ffe3e9e971000ab9c80c7e06aba2933aae5419d0e44693e3046913e9e58053f629183855260c9825260408520600160ff19825416179055604051908152a280f35b610f1d9193505f90611330565b5f916020610ecb565b6040513d5f823e3d90fd5b50805f5260cd60205260ff60405f20541690635a08a53760e01b5f52600452600160245260445260645ffd5b63921f325560e01b5f523360045260245ffd5b346106cf5760203660031901126106cf57610f89611291565b610fc27f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610afe308214156113a2565b610fca611484565b602090604051610fda8382611330565b5f815282810190601f1984013683377f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561102157505061101f9150611584565b005b6040516352d1902d60e01b81526001600160a01b038416908581600481855afa5f918161123f575b506110aa5760405162461bcd60e51b815260048101879052602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608490fd5b5f5160206116775f395f51905f52036111e8576110c684611584565b604051907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a28151158015906111e1575b6110ff57005b833b15611190575061101f93925f92839251915af43d15611188573d9061112582611366565b916111336040519384611330565b82523d5f8484013e5b7f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6040519361116c606086611330565b60278552840152660819985a5b195960ca1b604084015261161b565b60609061113c565b62461bcd60e51b815260048101859052602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608490fd5b505f6110f9565b60405162461bcd60e51b815260048101869052602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608490fd5b9091508681813d8311611267575b6112578183611330565b810103126106cf57519087611049565b503d61124d565b346106cf575f3660031901126106cf5760ca546001600160a01b03168152602090f35b600435906001600160a01b03821682036106cf57565b9181601f840112156106cf5782359167ffffffffffffffff83116106cf57602083818601950101116106cf57565b9060806003198301126106cf576004359160243567ffffffffffffffff81116106cf5781611305916004016112a7565b929092916044359067ffffffffffffffff82116106cf57611328916004016112a7565b909160643590565b90601f8019910116810190811067ffffffffffffffff82111761135257604052565b634e487b7160e01b5f52604160045260245ffd5b67ffffffffffffffff811161135257601f01601f191660200190565b60409060031901126106cf576004359060243560ff811681036106cf5790565b156113a957565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b19195b1959d85d1958d85b1b60a21b6064820152608490fd5b1561140a57565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b6163746976652070726f787960a01b6064820152608490fd5b908060209392818452848401375f828201840152601f01601f1916010190565b6033546001600160a01b0316330361149857565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b603380546001600160a01b039283166001600160a01b0319821681179092559091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b1561152b57565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b803b156115c05760018060a01b03166001600160601b0360a01b5f5160206116775f395f51905f525416175f5160206116775f395f51905f5255565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b90919015611627575090565b8151156116375750805190602001fd5b604460209160405192839162461bcd60e51b83528160048401528051918291826024860152018484015e5f828201840152601f01601f19168101030190fdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca26469706673582212203e7e5275dcfca1338183e642d2f8d1533c6f7ddb79bfa75ca00d0fd6b2d405ca64736f6c634300081b0033","sourceMap":"687:8719:41:-:0;;;;;;;1332:4:5;1324:13;;5456::4;687:8719:41;;;;;;;;;;;;;;5527:30:4;5523:138;;-1:-1:-1;687:8719:41;;;;;;;;1324:13:5;687:8719:41;;;;;;;;;;;;;;;;5523:138:4;687:8719:41;;;;;;5456:13:4;687:8719:41;5622:28:4;687:8719:41;;;;;;5622:28:4;5523:138;;;687:8719:41;-1:-1:-1;;;687:8719:41;;;;;;;;;;;;;;;;;-1:-1:-1;;;687:8719:41;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x6080806040526004361015610012575f80fd5b5f905f3560e01c908163294e3ccb1461126e575080633659cfe614610f7057806339ad96d914610e1757806342af056814610dea5780634c46688c14610dc15780634f1ef28614610a5457806352d1902d1461099157806355a9a7bf146108e8578063616af4f7146108bf5780636eecb4c9146108a3578063715018a61461084657806383501b211461082a5780638da5cb5b14610801578063972e58ba146107e557806398dc5b03146107b65780639eade0f11461074e578063a52f681b146106e6578063be96ce9314610563578063d5d8d0a8146104d8578063e03e3691146103ae578063f28c3e37146101a35763f2fde38b14610110575f80fd5b346101a05760203660031901126101a057610129611291565b610131611484565b6001600160a01b0381161561014c57610149906114dc565b80f35b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b80fd5b50346101a05760c03660031901126101a0576101bd611291565b6024356001600160a01b038116908190036103aa576044356001600160a01b038116908190036103a6576064356001600160a01b03811692908390036103a257845460ff8160081c161594858096610395575b801561037e575b156103225760ff19821660011787556102689186610311575b5061024a60ff885460081c1661024581611524565b611524565b610253336114dc565b61026360ff885460081c16611524565b6114dc565b6001600160601b0360a01b60cb54161760cb556001600160601b0360a01b60ca54161760ca556001600160601b0360a01b60cc54161760cc55608435825260cd60205260408220600260ff1982541617905560a435825260cd60205260408220600160ff198254161790556102da5780f35b61ff001981541681557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160018152a180f35b61ffff19166101011787555f610230565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b50303b1580156102175750600160ff831614610217565b50600160ff831610610210565b8480fd5b8380fd5b8280fd5b50346101a05760803660031901126101a05760043567ffffffffffffffff81116104d457366023820112156104d45780600401359067ffffffffffffffff82116103aa573660248360051b830101116103aa5760243561ffff811681036103a65760643567ffffffffffffffff81116103a25761047161043460429236906004016112a7565b929083604051948592602084019761ffff60f01b9060f01b168852604435602285015284840137810188838201520301601f198101835282611330565b5190209083915b838310156104b95760248360051b83010135908181105f146104a85785526020526001604085205b920191610478565b9085526020526001604085206104a0565b60ff604086602093815260c984522054166040519015158152f35b5080fd5b50346101a05760ff6104e936611382565b6104f4929192611484565b16600181141580610558575b6105465760207e86b661a41d941418d5d36446dc66bee8596027431ea48aba1cdbf9ab8cbada9183855260cd8252604085208160ff19825416179055604051908152a280f35b633212f51f60e21b8352600452602482fd5b506002811415610500565b50346101a057610572366112d5565b60cb5492959493929091906001600160a01b031633036106d35760208682810103126106cf5785359582885260cd602052600260ff60408a205416036106a3578782602092829796959460405192839283378101838152039060025afa156106985783519260018060a01b0360cc541690813b15610694578593610615936040519687958694859463ab750e7560e01b8652606060048701526064860191611464565b916024840152604483015203915afa801561068957610674575b507ffe3e9e971000ab9c80c7e06aba2933aae5419d0e44693e3046913e9e58053f6291836020925260c9825260408520600160ff19825416179055604051908152a280f35b8161067e91611330565b6103aa57825f61062f565b6040513d84823e3d90fd5b8580fd5b6040513d85823e3d90fd5b82885260cd6020526040882054635a08a53760e01b89526004849052600260245260ff16604452606488fd5b5f80fd5b63921f325560e01b875233600452602487fd5b50346101a05760203660031901126101a057610700611291565b610708611484565b60cc80546001600160a01b0319166001600160a01b039290921691821790557f80ad03c31df486a2ab8f2fe1f9e0597e290255e749369a3e0cf3b1cf34b180898280a280f35b50346101a05760203660031901126101a057610768611291565b610770611484565b60ca80546001600160a01b0319166001600160a01b039290921691821790557fc34d8b9ef5ec2845c44a69730b4523b5d66bc715b6d4820707ff1f40ee5f1a9e8280a280f35b50346101a05760203660031901126101a05760ff6040602092600435815260c984522054166040519015158152f35b50346101a057806003193601126101a057602060405160028152f35b50346101a057806003193601126101a0576033546040516001600160a01b039091168152602090f35b50346101a057806003193601126101a057602060405160ff8152f35b50346101a057806003193601126101a05761085f611484565b603380546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346101a057806003193601126101a057602060405160018152f35b50346101a057806003193601126101a05760cc546040516001600160a01b039091168152602090f35b50346101a05760ff6108f936611382565b610904929192611484565b16600181141580610986575b6105465781835260cd60205260ff6040842054169080820361096e575060207fca6a89a45ac13d034743c006df767832823ffba941ccc74cca0cb5dcd0abffaf9183855260cd82526040852060ff198154169055604051908152a280f35b63d4cec2bb60e01b8452600491909152602452604482fd5b506002811415610910565b50346101a057806003193601126101a0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031630036109e95760206040515f5160206116775f395f51905f528152f35b60405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608490fd5b5060403660031901126101a057610a69611291565b60243567ffffffffffffffff81116103aa57366023820112156103aa5780600401359083610a9683611366565b91610aa46040519384611330565b838352602083019336602482840101116103aa5780602460209301863783010152610b1c7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610afe308214156113a2565b5f5160206116775f395f51905f52546001600160a01b031614611403565b610b24611484565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610b5957505061014990611584565b6040516352d1902d60e01b81526001600160a01b03841690602081600481855afa869181610d89575b50610be35760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608490fd5b5f5160206116775f395f51905f5203610d3257610bff84611584565b604051907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8680a2815115801590610d2a575b610c3e575b5050505080f35b833b15610cd95750610cc8928492839251915af43d15610cd2573d610c6281611366565b90610c706040519283611330565b81523d84602083013e5b60405191610c89606084611330565b602783527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6020840152660819985a5b195960ca1b604084015261161b565b505f808080610c37565b6060610c7a565b62461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608490fd5b506001610c32565b60405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608490fd5b9091506020813d602011610db9575b81610da560209383611330565b81010312610db55751905f610b82565b8680fd5b3d9150610d98565b50346101a057806003193601126101a05760cb546040516001600160a01b039091168152602090f35b50346101a05760203660031901126101a05760ff6040602092600435815260cd8452205416604051908152f35b50346106cf57610e26366112d5565b60cb5493959491936001600160a01b03163303610f5d5760208287810103126106cf57813595815f5260cd602052600160ff60405f20541603610f315760ca546001600160a01b031691823b156106cf57610ebc5f95610eaa976040519889978896879663020a49e360e51b88526004880152606060248801526064870191611464565b84810360031901604486015291611464565b03915afa8015610f2657610f10575b5060207ffe3e9e971000ab9c80c7e06aba2933aae5419d0e44693e3046913e9e58053f629183855260c9825260408520600160ff19825416179055604051908152a280f35b610f1d9193505f90611330565b5f916020610ecb565b6040513d5f823e3d90fd5b50805f5260cd60205260ff60405f20541690635a08a53760e01b5f52600452600160245260445260645ffd5b63921f325560e01b5f523360045260245ffd5b346106cf5760203660031901126106cf57610f89611291565b610fc27f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610afe308214156113a2565b610fca611484565b602090604051610fda8382611330565b5f815282810190601f1984013683377f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561102157505061101f9150611584565b005b6040516352d1902d60e01b81526001600160a01b038416908581600481855afa5f918161123f575b506110aa5760405162461bcd60e51b815260048101879052602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608490fd5b5f5160206116775f395f51905f52036111e8576110c684611584565b604051907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a28151158015906111e1575b6110ff57005b833b15611190575061101f93925f92839251915af43d15611188573d9061112582611366565b916111336040519384611330565b82523d5f8484013e5b7f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6040519361116c606086611330565b60278552840152660819985a5b195960ca1b604084015261161b565b60609061113c565b62461bcd60e51b815260048101859052602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608490fd5b505f6110f9565b60405162461bcd60e51b815260048101869052602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608490fd5b9091508681813d8311611267575b6112578183611330565b810103126106cf57519087611049565b503d61124d565b346106cf575f3660031901126106cf5760ca546001600160a01b03168152602090f35b600435906001600160a01b03821682036106cf57565b9181601f840112156106cf5782359167ffffffffffffffff83116106cf57602083818601950101116106cf57565b9060806003198301126106cf576004359160243567ffffffffffffffff81116106cf5781611305916004016112a7565b929092916044359067ffffffffffffffff82116106cf57611328916004016112a7565b909160643590565b90601f8019910116810190811067ffffffffffffffff82111761135257604052565b634e487b7160e01b5f52604160045260245ffd5b67ffffffffffffffff811161135257601f01601f191660200190565b60409060031901126106cf576004359060243560ff811681036106cf5790565b156113a957565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b19195b1959d85d1958d85b1b60a21b6064820152608490fd5b1561140a57565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b6163746976652070726f787960a01b6064820152608490fd5b908060209392818452848401375f828201840152601f01601f1916010190565b6033546001600160a01b0316330361149857565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b603380546001600160a01b039283166001600160a01b0319821681179092559091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b1561152b57565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b803b156115c05760018060a01b03166001600160601b0360a01b5f5160206116775f395f51905f525416175f5160206116775f395f51905f5255565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b90919015611627575090565b8151156116375750805190602001fd5b604460209160405192839162461bcd60e51b83528160048401528051918291826024860152018484015e5f828201840152601f01601f19168101030190fdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca26469706673582212203e7e5275dcfca1338183e642d2f8d1533c6f7ddb79bfa75ca00d0fd6b2d405ca64736f6c634300081b0033","sourceMap":"687:8719:41:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;687:8719:41;;;;;;:::i;:::-;1303:62:0;;:::i;:::-;-1:-1:-1;;;;;687:8719:41;;2409:22:0;687:8719:41;;2503:8:0;;;:::i;:::-;687:8719:41;;;;;-1:-1:-1;;;687:8719:41;;;;;;;;;;;;;;;;;-1:-1:-1;;;687:8719:41;;;;;;;;;;;;;;;;;-1:-1:-1;;687:8719:41;;;;;;:::i;:::-;;;-1:-1:-1;;;;;687:8719:41;;;;;;;;;;-1:-1:-1;;;;;687:8719:41;;;;;;;;;;-1:-1:-1;;;;;687:8719:41;;;;;;;;;;;;;;;;3133:14:4;;;;3179:34;;;687:8719:41;3178:108:4;;;;687:8719:41;;;;-1:-1:-1;;687:8719:41;;;;;;2762:8;;687:8719;3394:65:4;;687:8719:41;;4902:69:4;687:8719:41;;;;;;4902:69:4;;;:::i;:::-;;:::i;:::-;1195:12:0;929:10:7;1195:12:0;:::i;:::-;4902:69:4;687:8719:41;;;;;;4902:69:4;:::i;:::-;2762:8:41;:::i;:::-;-1:-1:-1;;;;;687:8719:41;;2781:52;687:8719;;;2781:52;687:8719;-1:-1:-1;;;;;687:8719:41;;2843:40;687:8719;;;2843:40;687:8719;-1:-1:-1;;;;;687:8719:41;;2893:44;687:8719;;;2893:44;687:8719;;;;;2947:29;687:8719;;;;;;;;;;;;;;;;;;2947:29;687:8719;;;;;;;;;;;;;;3479:99:4;;687:8719:41;;3479:99:4;687:8719:41;;;;;;;3553:14:4;687:8719:41;;;;;;3553:14:4;687:8719:41;;3394:65:4;-1:-1:-1;;687:8719:41;;;;;3394:65:4;;;687:8719:41;;;-1:-1:-1;;;687:8719:41;;;;;;;;;;;;;;;;;-1:-1:-1;;;687:8719:41;;;;;;;3178:108:4;3258:4;;1476:19:6;:23;3219:66:4;;3178:108;3219:66;687:8719:41;;;;;3268:17:4;3178:108;;3179:34;687:8719:41;;;;;3197:16:4;3179:34;;687:8719:41;;;;;;;;;;;;;;;;;;;-1:-1:-1;;687:8719:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6123:66;687:8719;;;;;;;;:::i;:::-;;;;;;6123:66;;;687:8719;6123:66;;687:8719;;;;;;;;;;;;;;;;;;;;;;;;;;;6123:66;;687:8719;;6123:66;;;;;;:::i;:::-;687:8719;6113:77;;2480:13:35;;2475:116;2513:3;2495:16;;;;;;687:8719:41;;;;;;;;9318:51:35;:5;;;:51;:5;;;9632:119;;687:8719:41;9632:119:35;687:8719:41;;9632:119:35;;9318:51;2513:3;687:8719:41;2480:13:35;;;9318:51;9632:119;;;687:8719:41;9632:119:35;687:8719:41;;9632:119:35;;9318:51;;2495:16;687:8719:41;;2495:16:35;687:8719:41;2495:16:35;687:8719:41;;6299:20;687:8719;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1303:62:0;;;;;:::i;:::-;687:8719:41;2018:1;6845:25;;;:68;;;687:8719;6841:184;;687:8719;8349:66;687:8719;;;;8260:29;687:8719;;;;;;;;;;;;;;;;;;;8349:66;687:8719;;6841:184;-1:-1:-1;;;6939:71:41;;687:8719;;;6939:71;;6845:68;6886:27;2103:1;6886:27;;;6845:68;;687:8719;;;;;;;;:::i;:::-;6568:24;687:8719;;;;;;;;;-1:-1:-1;;;;;687:8719:41;6554:10;:38;6550:109;;687:8719;4102:40;;;;687:8719;;;;;;;;;;4157:29;687:8719;;2103:1;687:8719;;;;;;4157:68;4153:224;;687:8719;;;;;;;;;;;;;;;;;;;;;4416:25;;2103:1;4416:25;;;;;;;687:8719;;;;;;4469:20;687:8719;;4451:133;;;;;;687:8719;;;;;;;;;;;;;;;;4451:133;;687:8719;;4451:133;;687:8719;;;;;;:::i;:::-;;;;;;;;;;4451:133;;;;;;;;;;687:8719;;4649:54;687:8719;;;;;4595:20;687:8719;;;;;4630:4;687:8719;;;;;;;;;;;;;4649:54;687:8719;;4451:133;;;;;:::i;:::-;687:8719;;4451:133;;;;;687:8719;;;;;;;;;4451:133;687:8719;;;4416:25;687:8719;;;;;;;;;4153:224;687:8719;;;4157:29;687:8719;;;;;;-1:-1:-1;;;4248:118:41;;687:8719;;;;2103:1;687:8719;;;;;;;;4248:118;687:8719;-1:-1:-1;687:8719:41;;6550:109;-1:-1:-1;;;6615:33:41;;6554:10;687:8719;;;6615:33;;687:8719;;;;;;;-1:-1:-1;;687:8719:41;;;;;;:::i;:::-;1303:62:0;;:::i;:::-;7291:44:41;687:8719;;-1:-1:-1;;;;;;687:8719:41;-1:-1:-1;;;;;687:8719:41;;;;;;;;;7350:50;;;;687:8719;;;;;;;;;-1:-1:-1;;687:8719:41;;;;;;:::i;:::-;1303:62:0;;:::i;:::-;7645:40:41;687:8719;;-1:-1:-1;;;;;;687:8719:41;-1:-1:-1;;;;;687:8719:41;;;;;;;;;7700:46;;;;687:8719;;;;;;;;;-1:-1:-1;;687:8719:41;;;;;;;;;;;;884:52;687:8719;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2103:1;687:8719;;;;;;;;;;;;;;;;1513:6:0;687:8719:41;;;-1:-1:-1;;;;;687:8719:41;;;;;;;;;;;;;;;;;;;;;;;;1933:4;687:8719;;;;;;;;;;;;;;;;1303:62:0;;:::i;:::-;2765:6;687:8719:41;;-1:-1:-1;;;;;;687:8719:41;;;;;;;-1:-1:-1;;;;;687:8719:41;2813:40:0;687:8719:41;;2813:40:0;687:8719:41;;;;;;;;;;;;;;;;;;2018:1;687:8719;;;;;;;;;;;;;;;;1699:35;687:8719;;;-1:-1:-1;;;;;687:8719:41;;;;;;;;;;;;;;;;;:::i;:::-;1303:62:0;;;;;:::i;:::-;687:8719:41;2018:1;6845:25;;;:68;;;687:8719;6841:184;;687:8719;;;8918:29;687:8719;;;;;;;;9074:37;;;;9070:167;;687:8719;;9325:72;687:8719;;;;8918:29;687:8719;;;;;;;;;;;;;;;;;9325:72;687:8719;;9070:167;-1:-1:-1;;;9134:92:41;;687:8719;;;;;;;;9134:92;;6845:68;6886:27;2103:1;6886:27;;;6845:68;;687:8719;;;;;;;;;;;;;2333:6:5;-1:-1:-1;;;;;687:8719:41;2324:4:5;2316:23;687:8719:41;;;;;-1:-1:-1;;;;;;;;;;;687:8719:41;;;;;;-1:-1:-1;;;687:8719:41;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;687:8719:41;;-1:-1:-1;;687:8719:41;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;1963:87:5;1898:6;-1:-1:-1;;;;;687:8719:41;1873:80:5;1889:4;1881:23;;;1873:80;:::i;:::-;-1:-1:-1;;;;;;;;;;;687:8719:41;-1:-1:-1;;;;;687:8719:41;1971:30:5;1963:87;:::i;:::-;1303:62:0;;:::i;:::-;951:66:2;687:8719:41;;;;;;3478:17:2;;;;;:::i;3380:526::-;687:8719:41;;-1:-1:-1;;;3531:63:2;;-1:-1:-1;;;;;687:8719:41;;;;;;;;3531:63:2;;;;;;;3380:526;-1:-1:-1;3527:302:2;;687:8719:41;;-1:-1:-1;;;3758:56:2;;687:8719:41;;3758:56:2;;951:66;;687:8719:41;951:66:2;;687:8719:41;951:66:2;687:8719:41;;;951:66:2;-1:-1:-1;;;951:66:2;;;;3758:56;;;3527:302;-1:-1:-1;;;;;;;;;;;3644:28:2;951:66;;2277:17;;;:::i;:::-;687:8719:41;;2310:27:2;;;;;687:8719:41;;2659:15:2;;;:28;;;3527:302;2655:105;;3527:302;3380:526;;;;687:8719:41;;2655:105:2;1476:19:6;;:23;687:8719:41;;7395:25:2;7437:99;7395:25;;;;;;;;;687:8719:41;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;;687:8719:41;;;;7437:99:2;:::i;:::-;;2655:105;;;;;;687:8719:41;;;;;-1:-1:-1;;;687:8719:41;;;;;;;;;;;;;;;;;-1:-1:-1;;;687:8719:41;;;;;;;2659:28:2;;3971:4:5;2659:28:2;;951:66;687:8719:41;;-1:-1:-1;;;951:66:2;;687:8719:41;;951:66:2;;;;687:8719:41;951:66:2;;687:8719:41;951:66:2;687:8719:41;;;951:66:2;-1:-1:-1;;;951:66:2;;;;;;;3531:63;;;;687:8719:41;3531:63:2;;687:8719:41;3531:63:2;;;;;;687:8719:41;3531:63:2;;;:::i;:::-;;;951:66;;;;;3531:63;;;;951:66;687:8719:41;;;3531:63:2;;;-1:-1:-1;3531:63:2;;687:8719:41;;;;;;;;;;;;;1454:39;687:8719;;;-1:-1:-1;;;;;687:8719:41;;;;;;;;;;;;;;;-1:-1:-1;;687:8719:41;;;;;;;;;;;;2262:62;687:8719;;;;;;;;;;;;;;;;;;;:::i;:::-;6568:24;687:8719;;;;;;-1:-1:-1;;;;;687:8719:41;6554:10;:38;6550:109;;687:8719;3345:38;;;;687:8719;;;;;;;;;;3398:29;687:8719;;2018:1;687:8719;;;;;;3398:66;3394:220;;3637:18;687:8719;-1:-1:-1;;;;;687:8719:41;;3624:103;;;;;687:8719;;;;;;;;;;;;;;;;;3624:103;;687:8719;3624:103;;687:8719;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;687:8719:41;;;;;;;:::i;:::-;3624:103;;;;;;;;;;687:8719;;;3792:54;687:8719;;;;3738:20;687:8719;;;;;2018:1;687:8719;;;;;;;;;;;;;3792:54;687:8719;;3624:103;;;;;687:8719;3624:103;;:::i;:::-;687:8719;;;3624:103;;;687:8719;;;;;;;;;3394:220;687:8719;;;;3398:29;687:8719;;;;;;;;3487:116;;;;687:8719;3487:116;687:8719;;2018:1;687:8719;;;;;;3487:116;6550:109;6615:33;;;687:8719;6615:33;6554:10;687:8719;;;;6615:33;687:8719;;;;;;-1:-1:-1;;687:8719:41;;;;;;:::i;:::-;1963:87:5;1898:6;-1:-1:-1;;;;;687:8719:41;1873:80:5;1889:4;1881:23;;;1873:80;:::i;1963:87::-;1303:62:0;;:::i;:::-;687:8719:41;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;687:8719:41;;;;;951:66:2;687:8719:41;;;;;;3478:17:2;;;;;;:::i;:::-;687:8719:41;3380:526:2;687:8719:41;;-1:-1:-1;;;3531:63:2;;-1:-1:-1;;;;;687:8719:41;;;3531:63:2;687:8719:41;;;;3531:63:2;;687:8719:41;;3531:63:2;;;3380:526;-1:-1:-1;3527:302:2;;687:8719:41;;-1:-1:-1;;;3758:56:2;;687:8719:41;3758:56:2;;951:66;;;;;;;687:8719:41;951:66:2;687:8719:41;;;951:66:2;-1:-1:-1;;;951:66:2;;;;3758:56;;;3527:302;-1:-1:-1;;;;;;;;;;;3644:28:2;951:66;;2277:17;;;:::i;:::-;687:8719:41;;2310:27:2;;687:8719:41;2310:27:2;;687:8719:41;;2659:15:2;;;:28;;;3527:302;2655:105;;687:8719:41;2655:105:2;1476:19:6;;:23;687:8719:41;;7395:25:2;7437:99;7395:25;;687:8719:41;7395:25:2;;;;;;;687:8719:41;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;687:8719:41;;;;7437:99:2;:::i;687:8719:41:-;;;;;;-1:-1:-1;;;687:8719:41;;;;;;;;;;;;;;;;;;-1:-1:-1;;;687:8719:41;;;;;;;2659:28:2;;687:8719:41;2659:28:2;;951:66;687:8719:41;;-1:-1:-1;;;951:66:2;;687:8719:41;951:66:2;;;;;;;;;687:8719:41;951:66:2;687:8719:41;;;951:66:2;-1:-1:-1;;;951:66:2;;;;;;;3531:63;;;;;;;;;;;;;;;;;:::i;:::-;;;951:66;;;;;3531:63;;;;;;;;;687:8719:41;;;;;;-1:-1:-1;;687:8719:41;;;;1327:33;687:8719;-1:-1:-1;;;;;687:8719:41;;;;;;;;;;-1:-1:-1;;;;;687:8719:41;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;687:8719:41;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;-1:-1:-1;687:8719:41;;;;;-1:-1:-1;687:8719:41;;;;;;;;;-1:-1:-1;;687:8719:41;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::o;:::-;;;-1:-1:-1;;;687:8719:41;;;;;;;;;;;;;;;;;-1:-1:-1;;;687:8719:41;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;687:8719:41;;;;;;;;;;;;;;;;;-1:-1:-1;;;687:8719:41;;;;;;;;;;;;;;;;;;;;-1:-1:-1;687:8719:41;;;;;;;;-1:-1:-1;;687:8719:41;;;;:::o;1599:130:0:-;1513:6;687:8719:41;-1:-1:-1;;;;;687:8719:41;929:10:7;1662:23:0;687:8719:41;;1599:130:0:o;687:8719:41:-;;;;951:66:2;;;687:8719:41;;;;;;;;;;;;;;;;;;2673:187:0;2765:6;687:8719:41;;-1:-1:-1;;;;;687:8719:41;;;-1:-1:-1;;;;;;687:8719:41;;;;;;;;;;2813:40:0;-1:-1:-1;;2813:40:0;2673:187::o;687:8719:41:-;;;;:::o;:::-;;;-1:-1:-1;;;687:8719:41;;;;;;;;;;;;;;;;;-1:-1:-1;;;687:8719:41;;;;;;;1805:281:2;1476:19:6;;:23;687:8719:41;;;;;;;;-1:-1:-1;;;;;687:8719:41;;-1:-1:-1;;;;;;;;;;;687:8719:41;;;-1:-1:-1;;;;;;;;;;;687:8719:41;1805:281:2:o;687:8719:41:-;;;-1:-1:-1;;;687:8719:41;;;;;;;;;;;;;;;;;-1:-1:-1;;;687:8719:41;;;;;;;6622:742:6;;;;6792:566;;;6819:17;;:::o;6792:566::-;687:8719:41;;6937:21:6;:17;;7121:154;;;;;;;6933:415;687:8719:41;;;;;951:66:2;;;;;;7313:20:6;;;;;;687:8719:41;;;;;;;;;;;;;;;;6957:1:6;687:8719:41;;;;;;;;-1:-1:-1;;687:8719:41;;;7313:20:6;;;","linkReferences":{},"immutableReferences":{"702":[{"start":2468,"length":32},{"start":2762,"length":32},{"start":3982,"length":32}]}},"methodIdentifiers":{"RISC0_ID()":"972e58ba","SP1_ID()":"6eecb4c9","VERIFIER_MOCK_ADDRESS()":"83501b21","alignedAggregatorAddress()":"4c46688c","allowVerifyingProgram(bytes32,uint8)":"d5d8d0a8","allowedVerifiersProvingSystem(bytes32)":"42af0568","disallowVerifyingProgram(bytes32,uint8)":"55a9a7bf","initialize(address,address,address,address,bytes32,bytes32)":"f28c3e37","isMerkleRootVerified(bytes32)":"98dc5b03","isProofVerified(bytes32[],uint16,bytes32,bytes)":"e03e3691","owner()":"8da5cb5b","proxiableUUID()":"52d1902d","renounceOwnership()":"715018a6","risc0VerifierAddress()":"616af4f7","setRisc0VerifierAddress(address)":"a52f681b","setSP1VerifierAddress(address)":"9eade0f1","sp1VerifierAddress()":"294e3ccb","transferOwnership(address)":"f2fde38b","upgradeTo(address)":"3659cfe6","upgradeToAndCall(address,bytes)":"4f1ef286","verifyAggregationRisc0(bytes32,bytes,bytes,bytes32)":"be96ce93","verifyAggregationSP1(bytes32,bytes,bytes,bytes32)":"39ad96d9"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidProvingSystemId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"verifierProgramCommitment\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidVerifyingProgram\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"OnlyAlignedAggregator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"received\",\"type\":\"uint8\"}],\"name\":\"ProvingSystemIdMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"blobVersionedHash\",\"type\":\"bytes32\"}],\"name\":\"AggregatedProofVerified\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAddress\",\"type\":\"address\"}],\"name\":\"Risc0VerifierAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAddress\",\"type\":\"address\"}],\"name\":\"SP1VerifierAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"verifierProgramCommitment\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"provingSystemId\",\"type\":\"uint8\"}],\"name\":\"VerifierProgramAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"verifierProgramCommitment\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"provingSystemId\",\"type\":\"uint8\"}],\"name\":\"VerifierProgramDisallowed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"RISC0_ID\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SP1_ID\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERIFIER_MOCK_ADDRESS\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"alignedAggregatorAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"verifierProgramCommitment\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"provingSystemId\",\"type\":\"uint8\"}],\"name\":\"allowVerifyingProgram\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"allowedVerifiersProvingSystem\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"verifierProgramCommitment\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"provingSystemId\",\"type\":\"uint8\"}],\"name\":\"disallowVerifyingProgram\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_alignedAggregatorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_sp1VerifierAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_risc0VerifierAddress\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_risc0AggregatorProgramImageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_sp1AggregatorProgramVKHash\",\"type\":\"bytes32\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"isMerkleRootVerified\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"merklePath\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint16\",\"name\":\"provingSystemId\",\"type\":\"uint16\"},{\"internalType\":\"bytes32\",\"name\":\"programCommitment\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"publicInputs\",\"type\":\"bytes\"}],\"name\":\"isProofVerified\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"risc0VerifierAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_risc0VerifierAddress\",\"type\":\"address\"}],\"name\":\"setRisc0VerifierAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sp1VerifierAddress\",\"type\":\"address\"}],\"name\":\"setSP1VerifierAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sp1VerifierAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"blobVersionedHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"risc0ReceiptSeal\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"risc0JournalBytes\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"verifierProgramCommitment\",\"type\":\"bytes32\"}],\"name\":\"verifyAggregationRisc0\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"blobVersionedHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"sp1PublicValues\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sp1ProofBytes\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"verifierProgramCommitment\",\"type\":\"bytes32\"}],\"name\":\"verifyAggregationSP1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"AdminChanged(address,address)\":{\"details\":\"Emitted when the admin account has changed.\"},\"BeaconUpgraded(address)\":{\"details\":\"Emitted when the beacon is upgraded.\"},\"Initialized(uint8)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"allowVerifyingProgram(bytes32,uint8)\":{\"params\":{\"provingSystemId\":\"The proving system ID associated with the verifying program.\",\"verifierProgramCommitment\":\"The verifying program commitment to allow (image ID for RISC0 or vk hash for SP1).\"}},\"disallowVerifyingProgram(bytes32,uint8)\":{\"params\":{\"verifierProgramCommitment\":\"The verifying program commitment to disallow (image ID for RISC0 or vk hash for SP1).\"}},\"isProofVerified(bytes32[],uint16,bytes32,bytes)\":{\"details\":\"- The `programCommitment` parameter represents the unique identifier for the vm program: - In RISC Zero, this corresponds to the `image_id`. - In SP1, this corresponds to the `vk` (verification key) hash. - The proof commitment is derived by hashing together the `programCommitment` and the `publicInputs`. - The `merklePath` is then used to compute the Merkle root from this commitment. - The function returns `true` if this Merkle root is known to correspond to a valid aggregated proof.\",\"params\":{\"merklePath\":\"The Merkle proof (sibling hashes) needed to reconstruct the Merkle root.\",\"programCommitment\":\"The commitment of the program sent to Aligned (image_id in RISC0 or vk hash in SP1).\",\"provingSystemId\":\"The id of the proving system (1 for SP1, 2 for RISC0).\",\"publicInputs\":\"The public inputs bytes of the proof sent to Aligned.\"},\"returns\":{\"_0\":\"bool Returns true if the computed Merkle root is a recognized valid aggregated proof.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate that the this implementation remains valid after an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setRisc0VerifierAddress(address)\":{\"params\":{\"_risc0VerifierAddress\":\"The new address for the Risc0 verifier contract\"}},\"setSP1VerifierAddress(address)\":{\"params\":{\"_sp1VerifierAddress\":\"The new address for the SP1 verifier contract\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"verifyAggregationSP1(bytes32,bytes,bytes,bytes32)\":{\"details\":\"This function is called by the aligned proof aggregator after collecting the proofs and aggregating them to be verified on-chain. We expect the blobTransactionHash to be called before\",\"params\":{\"blobVersionedHash\":\"the versioned hash of the blob transaction that contains the leaves that compose the merkle root.\",\"sp1ProofBytes\":\"Groth16 proof\",\"sp1PublicValues\":\"Values used to perform the execution\",\"verifierProgramCommitment\":\"The chunk aggregator verifier program commitment against which the proof should be verified\"}}},\"stateVariables\":{\"risc0VerifierAddress\":{\"details\":\"See supported verifier here: https://dev.risczero.com/api/blockchain-integration/contracts/verifier#contract-addresses\"},\"sp1VerifierAddress\":{\"details\":\"This can either be a specific SP1Verifier for a specific version, or the SP1VerifierGateway which can be used to verify proofs for any version of SP1. For the list of supported verifiers on each chain, see: https://docs.succinct.xyz/docs/sp1/verification/contract-addresses\"}},\"version\":1},\"userdoc\":{\"events\":{\"AggregatedProofVerified(bytes32,bytes32)\":{\"notice\":\"event that gets emitted after a successful aggregated proof verification\"},\"Risc0VerifierAddressUpdated(address)\":{\"notice\":\"Event emitted when the Risc0 verifier address is updated\"},\"SP1VerifierAddressUpdated(address)\":{\"notice\":\"Event emitted when the SP1 verifier address is updated\"},\"VerifierProgramAllowed(bytes32,uint8)\":{\"notice\":\"Event emitted when a verifier program is allowed\"},\"VerifierProgramDisallowed(bytes32,uint8)\":{\"notice\":\"Event emitted when a verifier program is disallowed\"}},\"kind\":\"user\",\"methods\":{\"RISC0_ID()\":{\"notice\":\"Proving system ID for RISC0\"},\"SP1_ID()\":{\"notice\":\"Proving system ID for SP1\"},\"VERIFIER_MOCK_ADDRESS()\":{\"notice\":\"whether we are in dev mode or not if the sp1 verifier address is set to this address, then we skip verification\"},\"alignedAggregatorAddress()\":{\"notice\":\"The address of the Wallet that is allowed to call the verify function.\"},\"allowVerifyingProgram(bytes32,uint8)\":{\"notice\":\"Allows a new verifying program commitment to the list of valid verifying programs.\"},\"allowedVerifiersProvingSystem(bytes32)\":{\"notice\":\"Maps allowed verifiers commitments to their proving system. If the verifier is not a valid one, it returns 0 and is considered invalid\"},\"disallowVerifyingProgram(bytes32,uint8)\":{\"notice\":\"Disallows a verifying program commitment from the list of valid verifying programs.\"},\"isMerkleRootVerified(bytes32)\":{\"notice\":\"true if merkle root is verified\"},\"isProofVerified(bytes32[],uint16,bytes32,bytes)\":{\"notice\":\"Verifies the inclusion of proof in an aggregated proof via Merkle tree proof.\"},\"risc0VerifierAddress()\":{\"notice\":\"The address of the Risc0 verifier contract\"},\"setRisc0VerifierAddress(address)\":{\"notice\":\"Sets the address of the Risc0 verifier contract\"},\"setSP1VerifierAddress(address)\":{\"notice\":\"Sets the address of the SP1 verifier contract\"},\"sp1VerifierAddress()\":{\"notice\":\"The address of the SP1 verifier contract.\"},\"verifyAggregationSP1(bytes32,bytes,bytes,bytes32)\":{\"notice\":\"Method to verify an aggregated proof from aligned\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/core/AlignedProofAggregationService.sol\":\"AlignedProofAggregationService\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@openzeppelin-upgrades-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/\",\":@openzeppelin-upgrades/contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/\",\":@risc0-contracts/=lib/risc0-ethereum/contracts/src/\",\":@sp1-contracts/=lib/sp1-contracts/contracts/src/\",\":ds-test/=lib/eigenlayer-middleware/lib/ds-test/src/\",\":eigenlayer-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/\",\":eigenlayer-core-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/\",\":eigenlayer-core/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/\",\":eigenlayer-middleware/=lib/eigenlayer-middleware/src/\",\":eigenlayer-scripts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/script/\",\":erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":halmos-cheatcodes/=lib/risc0-ethereum/lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts-upgradeable-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":openzeppelin/=lib/risc0-ethereum/lib/openzeppelin-contracts/\",\":risc0-ethereum/=lib/risc0-ethereum/\",\":sp1-contracts/=lib/sp1-contracts/contracts/\"],\"viaIR\":true},\"sources\":{\"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/interfaces/draft-IERC1822Upgradeable.sol\":{\"keccak256\":\"0x77c89f893e403efc6929ba842b7ccf6534d4ffe03afe31670b4a528c0ad78c0f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://496bd9b3df2455d571018c09f0c6badd29713fdeb907c6aa09d8d28cb603f053\",\"dweb:/ipfs/QmXdJDyYs6WMwMh21dez2BYPxhSUaUYFMDtVNcn2cgFR79\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol\":{\"keccak256\":\"0x315887e846f1e5f8d8fa535a229d318bb9290aaa69485117f1ee8a9a6b3be823\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://29dda00da6d269685b555e710e4abf1c3eb6d00c15b888a7880a2f8dd3c4fdc2\",\"dweb:/ipfs/QmSqcjtdECygtT1Gy7uEo42x8542srpgGEeKKHfcnQqXgn\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/proxy/beacon/IBeaconUpgradeable.sol\":{\"keccak256\":\"0x24b86ac8c005b8c654fbf6ac34a5a4f61580d7273541e83e013e89d66fbf0908\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4dbfe1a3b3b3fb64294ce41fd2ad362e7b7012208117864f42c1a67620a6d5c1\",\"dweb:/ipfs/QmVMU5tWt7zBQMmf5cpMX8UMHV86T3kFeTxBTBjFqVWfoJ\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"keccak256\":\"0x6e36e9b4b71de699c2f3f0d4e4d1aa0b35da99a26e8d5b91ef09ba234b4ef270\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://abfa467c53a0d60b4d09bf04aa952b1d1d44e5766fcc053aace078d7859b8419\",\"dweb:/ipfs/QmebVTZpyNxYfKYTuLMywzEJTdc1Ca8ME4xm3kR9gQgToG\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/utils/StorageSlotUpgradeable.sol\":{\"keccak256\":\"0x09864aea84f01e39313375b5610c73a3c1c68abbdc51e5ccdd25ff977fdadf9a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://aedb48081190fa828d243529ce25c708202c7d4ccfe99f0e4ecd6bc0cfcd03f3\",\"dweb:/ipfs/QmWyiDQHPZA56iqsAwTmiJoxvNeRQLUVr4gTfzpdpXivpo\"]},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol\":{\"keccak256\":\"0x6400c4bee15052e043e5d10315135972529bd1c8012f43da494dc6b4f4661058\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://da5d3d47d35af4373743a559ea4b9b7ecfe4bab6f0703f410c1e59959b7966ac\",\"dweb:/ipfs/QmTHdoghh4WLu4yURjGEgRk162pcwwdsG52MPGa12GqnGR\"]},\"lib/risc0-ethereum/contracts/src/IRiscZeroVerifier.sol\":{\"keccak256\":\"0x3e74a4b2940b88837fb8399a0012b435d1d513a622d3ea3ba58088af9ad7e2fd\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://b06299cc68e3c79e4eb22705bb814ce816a7fd549e78614b318ae44d35e56f9b\",\"dweb:/ipfs/QmPpX5ciRdEH6MVRVt7qYQqy7B68qxG5v3mxkgYm3kGxi5\"]},\"lib/risc0-ethereum/contracts/src/Util.sol\":{\"keccak256\":\"0x230a9a58bb2b0c68d4921ecc3672783f941890a2fa3a238dbe5188cfb7658b82\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://586cb5296c564761609ca8aaae5b1fbbdb19ab1e174f7197f602572d9e82b70c\",\"dweb:/ipfs/QmWxDmucSfg3Wgdk1rVcheDHwkziTsXWvKpKSCnxtpQBqg\"]},\"lib/sp1-contracts/contracts/src/ISP1Verifier.sol\":{\"keccak256\":\"0x9e3ba64860bea920772dcf16be7946de2a2900d80bd51e9c0771184138f4f4d3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0ec7230ca1fdd74edc6ab597d80bb345282aed3f0db4788ed96b4cc373ff46a3\",\"dweb:/ipfs/QmXPuSS5gzxMhFKWr1gsxBVu6WHh53ZZEvWkGgzrkM6Y7Q\"]},\"src/core/AlignedProofAggregationService.sol\":{\"keccak256\":\"0xb65ab88421d4d882c6c9edab50f98f1befe853265e0cd33358f7c4feabb7dd48\",\"license\":\"UNLICENSED\",\"urls\":[\"bzz-raw://4ff7e663616e715309af6970765a1bd7c35fbac40bfb284e33eed87778f80ac7\",\"dweb:/ipfs/QmaViYx6BGcgjJahvrNRw7yDd7MJM5TVkb651GJUYb6FcE\"]},\"src/core/IAlignedProofAggregationService.sol\":{\"keccak256\":\"0xddeb5c3e745f8b678be53d365fac9e84044cdacf898028dc243fc9ca2765cd2f\",\"urls\":[\"bzz-raw://c5fa9241c95d1535e081ad852eecae1bb4585948dcad5cdad57be9f5b8fd39eb\",\"dweb:/ipfs/QmcmRNaeuxFc7iQD1ExTzEWexdu2ksNyWZwe6sVK1mW4Gm\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.27+commit.40a35a09"},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint8","name":"actual","type":"uint8"}],"type":"error","name":"InvalidProvingSystemId"},{"inputs":[{"internalType":"bytes32","name":"verifierProgramCommitment","type":"bytes32"},{"internalType":"uint8","name":"expected","type":"uint8"},{"internalType":"uint8","name":"actual","type":"uint8"}],"type":"error","name":"InvalidVerifyingProgram"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"type":"error","name":"OnlyAlignedAggregator"},{"inputs":[{"internalType":"uint8","name":"expected","type":"uint8"},{"internalType":"uint8","name":"received","type":"uint8"}],"type":"error","name":"ProvingSystemIdMismatch"},{"inputs":[{"internalType":"address","name":"previousAdmin","type":"address","indexed":false},{"internalType":"address","name":"newAdmin","type":"address","indexed":false}],"type":"event","name":"AdminChanged","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"merkleRoot","type":"bytes32","indexed":true},{"internalType":"bytes32","name":"blobVersionedHash","type":"bytes32","indexed":false}],"type":"event","name":"AggregatedProofVerified","anonymous":false},{"inputs":[{"internalType":"address","name":"beacon","type":"address","indexed":true}],"type":"event","name":"BeaconUpgraded","anonymous":false},{"inputs":[{"internalType":"uint8","name":"version","type":"uint8","indexed":false}],"type":"event","name":"Initialized","anonymous":false},{"inputs":[{"internalType":"address","name":"previousOwner","type":"address","indexed":true},{"internalType":"address","name":"newOwner","type":"address","indexed":true}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"address","name":"newAddress","type":"address","indexed":true}],"type":"event","name":"Risc0VerifierAddressUpdated","anonymous":false},{"inputs":[{"internalType":"address","name":"newAddress","type":"address","indexed":true}],"type":"event","name":"SP1VerifierAddressUpdated","anonymous":false},{"inputs":[{"internalType":"address","name":"implementation","type":"address","indexed":true}],"type":"event","name":"Upgraded","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"verifierProgramCommitment","type":"bytes32","indexed":true},{"internalType":"uint8","name":"provingSystemId","type":"uint8","indexed":false}],"type":"event","name":"VerifierProgramAllowed","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"verifierProgramCommitment","type":"bytes32","indexed":true},{"internalType":"uint8","name":"provingSystemId","type":"uint8","indexed":false}],"type":"event","name":"VerifierProgramDisallowed","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"RISC0_ID","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"SP1_ID","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"VERIFIER_MOCK_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"alignedAggregatorAddress","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"bytes32","name":"verifierProgramCommitment","type":"bytes32"},{"internalType":"uint8","name":"provingSystemId","type":"uint8"}],"stateMutability":"nonpayable","type":"function","name":"allowVerifyingProgram"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function","name":"allowedVerifiersProvingSystem","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"bytes32","name":"verifierProgramCommitment","type":"bytes32"},{"internalType":"uint8","name":"provingSystemId","type":"uint8"}],"stateMutability":"nonpayable","type":"function","name":"disallowVerifyingProgram"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"},{"internalType":"address","name":"_alignedAggregatorAddress","type":"address"},{"internalType":"address","name":"_sp1VerifierAddress","type":"address"},{"internalType":"address","name":"_risc0VerifierAddress","type":"address"},{"internalType":"bytes32","name":"_risc0AggregatorProgramImageId","type":"bytes32"},{"internalType":"bytes32","name":"_sp1AggregatorProgramVKHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"function","name":"initialize"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function","name":"isMerkleRootVerified","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"bytes32[]","name":"merklePath","type":"bytes32[]"},{"internalType":"uint16","name":"provingSystemId","type":"uint16"},{"internalType":"bytes32","name":"programCommitment","type":"bytes32"},{"internalType":"bytes","name":"publicInputs","type":"bytes"}],"stateMutability":"view","type":"function","name":"isProofVerified","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"renounceOwnership"},{"inputs":[],"stateMutability":"view","type":"function","name":"risc0VerifierAddress","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"_risc0VerifierAddress","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"setRisc0VerifierAddress"},{"inputs":[{"internalType":"address","name":"_sp1VerifierAddress","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"setSP1VerifierAddress"},{"inputs":[],"stateMutability":"view","type":"function","name":"sp1VerifierAddress","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"upgradeTo"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"stateMutability":"payable","type":"function","name":"upgradeToAndCall"},{"inputs":[{"internalType":"bytes32","name":"blobVersionedHash","type":"bytes32"},{"internalType":"bytes","name":"risc0ReceiptSeal","type":"bytes"},{"internalType":"bytes","name":"risc0JournalBytes","type":"bytes"},{"internalType":"bytes32","name":"verifierProgramCommitment","type":"bytes32"}],"stateMutability":"nonpayable","type":"function","name":"verifyAggregationRisc0"},{"inputs":[{"internalType":"bytes32","name":"blobVersionedHash","type":"bytes32"},{"internalType":"bytes","name":"sp1PublicValues","type":"bytes"},{"internalType":"bytes","name":"sp1ProofBytes","type":"bytes"},{"internalType":"bytes32","name":"verifierProgramCommitment","type":"bytes32"}],"stateMutability":"nonpayable","type":"function","name":"verifyAggregationSP1"}],"devdoc":{"kind":"dev","methods":{"allowVerifyingProgram(bytes32,uint8)":{"params":{"provingSystemId":"The proving system ID associated with the verifying program.","verifierProgramCommitment":"The verifying program commitment to allow (image ID for RISC0 or vk hash for SP1)."}},"disallowVerifyingProgram(bytes32,uint8)":{"params":{"verifierProgramCommitment":"The verifying program commitment to disallow (image ID for RISC0 or vk hash for SP1)."}},"isProofVerified(bytes32[],uint16,bytes32,bytes)":{"details":"- The `programCommitment` parameter represents the unique identifier for the vm program: - In RISC Zero, this corresponds to the `image_id`. - In SP1, this corresponds to the `vk` (verification key) hash. - The proof commitment is derived by hashing together the `programCommitment` and the `publicInputs`. - The `merklePath` is then used to compute the Merkle root from this commitment. - The function returns `true` if this Merkle root is known to correspond to a valid aggregated proof.","params":{"merklePath":"The Merkle proof (sibling hashes) needed to reconstruct the Merkle root.","programCommitment":"The commitment of the program sent to Aligned (image_id in RISC0 or vk hash in SP1).","provingSystemId":"The id of the proving system (1 for SP1, 2 for RISC0).","publicInputs":"The public inputs bytes of the proof sent to Aligned."},"returns":{"_0":"bool Returns true if the computed Merkle root is a recognized valid aggregated proof."}},"owner()":{"details":"Returns the address of the current owner."},"proxiableUUID()":{"details":"Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate that the this implementation remains valid after an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier."},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner."},"setRisc0VerifierAddress(address)":{"params":{"_risc0VerifierAddress":"The new address for the Risc0 verifier contract"}},"setSP1VerifierAddress(address)":{"params":{"_sp1VerifierAddress":"The new address for the SP1 verifier contract"}},"transferOwnership(address)":{"details":"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."},"upgradeTo(address)":{"details":"Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event."},"upgradeToAndCall(address,bytes)":{"details":"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event."},"verifyAggregationSP1(bytes32,bytes,bytes,bytes32)":{"details":"This function is called by the aligned proof aggregator after collecting the proofs and aggregating them to be verified on-chain. We expect the blobTransactionHash to be called before","params":{"blobVersionedHash":"the versioned hash of the blob transaction that contains the leaves that compose the merkle root.","sp1ProofBytes":"Groth16 proof","sp1PublicValues":"Values used to perform the execution","verifierProgramCommitment":"The chunk aggregator verifier program commitment against which the proof should be verified"}}},"version":1},"userdoc":{"kind":"user","methods":{"RISC0_ID()":{"notice":"Proving system ID for RISC0"},"SP1_ID()":{"notice":"Proving system ID for SP1"},"VERIFIER_MOCK_ADDRESS()":{"notice":"whether we are in dev mode or not if the sp1 verifier address is set to this address, then we skip verification"},"alignedAggregatorAddress()":{"notice":"The address of the Wallet that is allowed to call the verify function."},"allowVerifyingProgram(bytes32,uint8)":{"notice":"Allows a new verifying program commitment to the list of valid verifying programs."},"allowedVerifiersProvingSystem(bytes32)":{"notice":"Maps allowed verifiers commitments to their proving system. If the verifier is not a valid one, it returns 0 and is considered invalid"},"disallowVerifyingProgram(bytes32,uint8)":{"notice":"Disallows a verifying program commitment from the list of valid verifying programs."},"isMerkleRootVerified(bytes32)":{"notice":"true if merkle root is verified"},"isProofVerified(bytes32[],uint16,bytes32,bytes)":{"notice":"Verifies the inclusion of proof in an aggregated proof via Merkle tree proof."},"risc0VerifierAddress()":{"notice":"The address of the Risc0 verifier contract"},"setRisc0VerifierAddress(address)":{"notice":"Sets the address of the Risc0 verifier contract"},"setSP1VerifierAddress(address)":{"notice":"Sets the address of the SP1 verifier contract"},"sp1VerifierAddress()":{"notice":"The address of the SP1 verifier contract."},"verifyAggregationSP1(bytes32,bytes,bytes,bytes32)":{"notice":"Method to verify an aggregated proof from aligned"}},"version":1}},"settings":{"remappings":["@openzeppelin-upgrades-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/","@openzeppelin-upgrades/contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/","@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/","@risc0-contracts/=lib/risc0-ethereum/contracts/src/","@sp1-contracts/=lib/sp1-contracts/contracts/src/","ds-test/=lib/eigenlayer-middleware/lib/ds-test/src/","eigenlayer-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/","eigenlayer-core-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/","eigenlayer-core/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/","eigenlayer-middleware/=lib/eigenlayer-middleware/src/","eigenlayer-scripts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/script/","erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","halmos-cheatcodes/=lib/risc0-ethereum/lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts-upgradeable-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/","openzeppelin-contracts/=lib/openzeppelin-contracts/","openzeppelin/=lib/risc0-ethereum/lib/openzeppelin-contracts/","risc0-ethereum/=lib/risc0-ethereum/","sp1-contracts/=lib/sp1-contracts/contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/core/AlignedProofAggregationService.sol":"AlignedProofAggregationService"},"evmVersion":"cancun","libraries":{},"viaIR":true},"sources":{"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol":{"keccak256":"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888","urls":["bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a","dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/interfaces/draft-IERC1822Upgradeable.sol":{"keccak256":"0x77c89f893e403efc6929ba842b7ccf6534d4ffe03afe31670b4a528c0ad78c0f","urls":["bzz-raw://496bd9b3df2455d571018c09f0c6badd29713fdeb907c6aa09d8d28cb603f053","dweb:/ipfs/QmXdJDyYs6WMwMh21dez2BYPxhSUaUYFMDtVNcn2cgFR79"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol":{"keccak256":"0x315887e846f1e5f8d8fa535a229d318bb9290aaa69485117f1ee8a9a6b3be823","urls":["bzz-raw://29dda00da6d269685b555e710e4abf1c3eb6d00c15b888a7880a2f8dd3c4fdc2","dweb:/ipfs/QmSqcjtdECygtT1Gy7uEo42x8542srpgGEeKKHfcnQqXgn"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/proxy/beacon/IBeaconUpgradeable.sol":{"keccak256":"0x24b86ac8c005b8c654fbf6ac34a5a4f61580d7273541e83e013e89d66fbf0908","urls":["bzz-raw://4dbfe1a3b3b3fb64294ce41fd2ad362e7b7012208117864f42c1a67620a6d5c1","dweb:/ipfs/QmVMU5tWt7zBQMmf5cpMX8UMHV86T3kFeTxBTBjFqVWfoJ"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol":{"keccak256":"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e","urls":["bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497","dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol":{"keccak256":"0x6e36e9b4b71de699c2f3f0d4e4d1aa0b35da99a26e8d5b91ef09ba234b4ef270","urls":["bzz-raw://abfa467c53a0d60b4d09bf04aa952b1d1d44e5766fcc053aace078d7859b8419","dweb:/ipfs/QmebVTZpyNxYfKYTuLMywzEJTdc1Ca8ME4xm3kR9gQgToG"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol":{"keccak256":"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3","urls":["bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4","dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol":{"keccak256":"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149","urls":["bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c","dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/utils/StorageSlotUpgradeable.sol":{"keccak256":"0x09864aea84f01e39313375b5610c73a3c1c68abbdc51e5ccdd25ff977fdadf9a","urls":["bzz-raw://aedb48081190fa828d243529ce25c708202c7d4ccfe99f0e4ecd6bc0cfcd03f3","dweb:/ipfs/QmWyiDQHPZA56iqsAwTmiJoxvNeRQLUVr4gTfzpdpXivpo"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol":{"keccak256":"0x6400c4bee15052e043e5d10315135972529bd1c8012f43da494dc6b4f4661058","urls":["bzz-raw://da5d3d47d35af4373743a559ea4b9b7ecfe4bab6f0703f410c1e59959b7966ac","dweb:/ipfs/QmTHdoghh4WLu4yURjGEgRk162pcwwdsG52MPGa12GqnGR"],"license":"MIT"},"lib/risc0-ethereum/contracts/src/IRiscZeroVerifier.sol":{"keccak256":"0x3e74a4b2940b88837fb8399a0012b435d1d513a622d3ea3ba58088af9ad7e2fd","urls":["bzz-raw://b06299cc68e3c79e4eb22705bb814ce816a7fd549e78614b318ae44d35e56f9b","dweb:/ipfs/QmPpX5ciRdEH6MVRVt7qYQqy7B68qxG5v3mxkgYm3kGxi5"],"license":"Apache-2.0"},"lib/risc0-ethereum/contracts/src/Util.sol":{"keccak256":"0x230a9a58bb2b0c68d4921ecc3672783f941890a2fa3a238dbe5188cfb7658b82","urls":["bzz-raw://586cb5296c564761609ca8aaae5b1fbbdb19ab1e174f7197f602572d9e82b70c","dweb:/ipfs/QmWxDmucSfg3Wgdk1rVcheDHwkziTsXWvKpKSCnxtpQBqg"],"license":"Apache-2.0"},"lib/sp1-contracts/contracts/src/ISP1Verifier.sol":{"keccak256":"0x9e3ba64860bea920772dcf16be7946de2a2900d80bd51e9c0771184138f4f4d3","urls":["bzz-raw://0ec7230ca1fdd74edc6ab597d80bb345282aed3f0db4788ed96b4cc373ff46a3","dweb:/ipfs/QmXPuSS5gzxMhFKWr1gsxBVu6WHh53ZZEvWkGgzrkM6Y7Q"],"license":"MIT"},"src/core/AlignedProofAggregationService.sol":{"keccak256":"0xb65ab88421d4d882c6c9edab50f98f1befe853265e0cd33358f7c4feabb7dd48","urls":["bzz-raw://4ff7e663616e715309af6970765a1bd7c35fbac40bfb284e33eed87778f80ac7","dweb:/ipfs/QmaViYx6BGcgjJahvrNRw7yDd7MJM5TVkb651GJUYb6FcE"],"license":"UNLICENSED"},"src/core/IAlignedProofAggregationService.sol":{"keccak256":"0xddeb5c3e745f8b678be53d365fac9e84044cdacf898028dc243fc9ca2765cd2f","urls":["bzz-raw://c5fa9241c95d1535e081ad852eecae1bb4585948dcad5cdad57be9f5b8fd39eb","dweb:/ipfs/QmcmRNaeuxFc7iQD1ExTzEWexdu2ksNyWZwe6sVK1mW4Gm"],"license":null}},"version":1},"id":41} diff --git a/aggregation_mode/sdk/src/beacon.rs b/aggregation_mode/sdk/src/beacon.rs new file mode 100644 index 000000000..ea78e6074 --- /dev/null +++ b/aggregation_mode/sdk/src/beacon.rs @@ -0,0 +1,154 @@ +use std::str::FromStr; + +use alloy::{hex, signers::k256::sha2::Sha256}; +use reqwest::{Client, Url}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use sha3::Digest; + +// See https://eips.ethereum.org/EIPS/eip-4844#parameters +pub const KZG_VERSIONED_HASH: u8 = 0x1; + +pub struct BeaconClient { + beacon_client_url: String, + api_client: Client, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(untagged)] +enum BeaconAPIResponse { + Success { data: Value }, + Error { code: u64, message: String }, +} + +#[derive(Debug, Clone)] +pub enum BeaconClientError { + Url(String), + ReqwestError(String), + APIError { code: u64, message: String }, + Deserialization(String), +} + +#[derive(Deserialize, Debug)] +#[allow(dead_code)] +// https://ethereum.github.io/beacon-APIs/#/Beacon/getBlobSidecars +pub struct BlobData { + pub index: String, + pub blob: String, + pub kzg_commitment: String, + pub kzg_proof: String, + pub kzg_commitment_inclusion_proof: Vec, +} + +#[derive(Deserialize, Debug)] +#[allow(dead_code)] +// https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockHeaders +pub struct BeaconBlock { + pub root: String, + pub canonical: bool, + pub header: BeaconBlockHeader, +} + +#[derive(Deserialize, Debug)] + +pub struct BeaconBlockHeader { + pub message: BeaconBlockMessage, +} + +#[derive(Deserialize, Debug)] +#[allow(dead_code)] +pub struct BeaconBlockMessage { + pub slot: String, + pub proposer_index: String, + pub parent_root: String, + pub state_root: String, + pub body_root: String, +} + +impl BeaconClient { + pub fn new(beacon_client_url: String) -> Self { + Self { + api_client: Client::new(), + beacon_client_url, + } + } + + pub async fn get_block_header_from_parent_hash( + &self, + parent_block_hash: [u8; 32], + ) -> Result, BeaconClientError> { + let parent_block_hash_hex = format!("0x{}", hex::encode(parent_block_hash)); + let data = self + .beacon_get(&format!( + "/eth/v1/beacon/headers?parent_root={}", + parent_block_hash_hex + )) + .await?; + + let res = Vec::::deserialize(data) + .map_err(|e| BeaconClientError::Deserialization(e.to_string()))?; + + let block = res + .into_iter() + .find(|block| block.header.message.parent_root == parent_block_hash_hex); + + Ok(block) + } + + pub async fn get_blobs_from_slot(&self, slot: u64) -> Result, BeaconClientError> { + let data = self + .beacon_get(&format!("/eth/v1/beacon/blob_sidecars/{}", slot)) + .await?; + + Vec::::deserialize(data) + .map_err(|e| BeaconClientError::Deserialization(e.to_string())) + } + + pub async fn get_blob_by_versioned_hash( + &self, + slot: u64, + blob_versioned_hash: [u8; 32], + ) -> Result, BeaconClientError> { + let res = self.get_blobs_from_slot(slot).await?; + + let blob = res.into_iter().find(|blob| { + let kzg_commitment_bytes = + hex::decode(blob.kzg_commitment.replace("0x", "")).expect("A valid commitment"); + + let mut hasher = Sha256::new(); + hasher.update(&kzg_commitment_bytes); + let mut versioned_hash: [u8; 32] = hasher.finalize().into(); + versioned_hash[0] = KZG_VERSIONED_HASH; + + versioned_hash == blob_versioned_hash + }); + + Ok(blob) + } + + async fn beacon_get(&self, path: &str) -> Result { + let url = Url::from_str(&format!("{}{}", self.beacon_client_url, path)) + .map_err(|e| BeaconClientError::Url(e.to_string()))?; + let req = self + .api_client + .get(url) + .header("content-type", "application/json") + .header("accept", "application/json"); + + let res = req + .send() + .await + .map_err(|e| BeaconClientError::ReqwestError(e.to_string()))?; + let beacon_response = res + .json() + .await + .map_err(|e| BeaconClientError::ReqwestError(e.to_string()))?; + + match beacon_response { + BeaconAPIResponse::Success { data } => Ok(data), + BeaconAPIResponse::Error { code, message } => { + Err(BeaconClientError::APIError { code, message }) + } + } + } +} diff --git a/aggregation_mode/sdk/src/blockchain/helpers.rs b/aggregation_mode/sdk/src/blockchain/helpers.rs new file mode 100644 index 000000000..47757aeb1 --- /dev/null +++ b/aggregation_mode/sdk/src/blockchain/helpers.rs @@ -0,0 +1,34 @@ +pub fn decoded_blob(blob_data: &[u8]) -> Vec<[u8; 32]> { + let mut proof_hashes = vec![]; + + let mut current_hash = [0u8; 32]; + let mut current_hash_count = 0; + let mut total_bytes_count = 0; + + while total_bytes_count < blob_data.len() { + // Every 32 bytes there is a 0x0 acting as padding, so we need to skip the byte + let is_pad = total_bytes_count % 32 == 0; + if is_pad { + total_bytes_count += 1; + continue; + } + + current_hash[current_hash_count] = blob_data[total_bytes_count]; + + if current_hash_count + 1 == 32 { + // if the current_hash is the zero hash, then there are no more proofs in the blob + if current_hash == [0u8; 32] { + break; + } + proof_hashes.push(current_hash); + current_hash = [0u8; 32]; + current_hash_count = 0; + } else { + current_hash_count += 1; + } + + total_bytes_count += 1; + } + + proof_hashes +} diff --git a/aggregation_mode/sdk/src/blockchain/mod.rs b/aggregation_mode/sdk/src/blockchain/mod.rs new file mode 100644 index 000000000..7edee55d4 --- /dev/null +++ b/aggregation_mode/sdk/src/blockchain/mod.rs @@ -0,0 +1,9 @@ +// Modules +mod helpers; +pub mod provider; +mod types; + +// Makes only the two types on this use public +pub use types::{ + AggregationModeProvingSystem, AggregationModeVerificationData, ProofVerificationAggModeError, +}; diff --git a/aggregation_mode/sdk/src/blockchain/provider.rs b/aggregation_mode/sdk/src/blockchain/provider.rs new file mode 100644 index 000000000..3b366daec --- /dev/null +++ b/aggregation_mode/sdk/src/blockchain/provider.rs @@ -0,0 +1,186 @@ +use crate::{ + beacon::BeaconClient, + blockchain::{ + helpers::decoded_blob, + types::{ + AlignedProofAggregationService, AlignedProofAggregationServiceContract, Hash32, + ProofStatus, RPCProvider, + }, + AggregationModeVerificationData, ProofVerificationAggModeError, + }, + types::Network, +}; +use alloy::{ + eips::BlockId, + hex, + primitives::Address, + providers::{Provider, ProviderBuilder}, + rpc::types::{Filter, Log}, +}; +use lambdaworks_crypto::merkle_tree::merkle::MerkleTree; +use std::str::FromStr; + +/// How much to go back from current block if from_block is not provided +/// 7500 blocks = 25hr +const FROM_BLOCKS_AGO_DEFAULT: u64 = 7500; + +pub struct ProofAggregationServiceProvider { + rpc_provider: RPCProvider, + beacon_client: BeaconClient, + proof_aggregation_service_contract: AlignedProofAggregationServiceContract, +} + +impl ProofAggregationServiceProvider { + pub fn new(network: Network, rpc_url: String, beacon_client_url: String) -> Self { + let rpc_url: reqwest::Url = rpc_url.parse().expect("rpc_url should be valid"); + let rpc_provider = ProviderBuilder::new().connect_http(rpc_url.clone()); + + let beacon_client = BeaconClient::new(beacon_client_url); + + let proof_aggregation_service_contract = AlignedProofAggregationService::new( + // safe unwrap, we know the address in network enum is valid + Address::from_str(&network.proof_aggregator_contract_address()).unwrap(), + rpc_provider.clone(), + ); + + Self { + rpc_provider, + proof_aggregation_service_contract, + beacon_client, + } + } + + pub async fn check_proof_verification( + &self, + from_block: Option, + verification_data: AggregationModeVerificationData, + ) -> Result { + let logs = self.fetch_verified_proofs_events(from_block).await?; + let proof_commitment = verification_data.commitment(); + + for log in logs { + let (merkle_root, leaves) = self.get_blob_data_from_verified_proof_event(log).await?; + + let leaves: Vec = leaves.iter().map(|leaf| Hash32(*leaf)).collect(); + + let Some(pos) = leaves.iter().position(|p| p.0 == proof_commitment) else { + continue; + }; + + let Some(merkle_tree) = MerkleTree::::build(&leaves) else { + continue; + }; + + let Some(proof) = merkle_tree.get_proof_by_pos(pos) else { + continue; + }; + + let result = proof.verify::(&merkle_root, pos, &Hash32(proof_commitment)); + if !result { + return Ok(ProofStatus::Invalid); + } + + return Ok(ProofStatus::Verified { + merkle_path: proof.merkle_path, + merkle_root, + }); + } + + Ok(ProofStatus::NotFound) + } + + async fn fetch_verified_proofs_events( + &self, + from_block: Option, + ) -> Result, ProofVerificationAggModeError> { + let from_block = match from_block { + Some(from_block) => from_block, + None => { + let block_number = self.rpc_provider.get_block_number().await.map_err(|e| { + ProofVerificationAggModeError::EthereumProviderError(e.to_string()) + })?; + + block_number.saturating_sub(FROM_BLOCKS_AGO_DEFAULT) + } + }; + + let filter = Filter::new() + .address(*self.proof_aggregation_service_contract.address()) + .event("AggregatedProofVerified(bytes32,bytes32)") + .from_block(from_block); + + let logs = self + .rpc_provider + .get_logs(&filter) + .await + .map_err(|e| ProofVerificationAggModeError::EthereumProviderError(e.to_string()))?; + + Ok(logs) + } + + async fn get_blob_data_from_verified_proof_event( + &self, + log: Log, + ) -> Result<([u8; 32], Vec<[u8; 32]>), ProofVerificationAggModeError> { + // First 32 bytes of the data are the bytes of the blob versioned hash + let blob_versioned_hash: [u8; 32] = log.data().data[0..32] + .try_into() + .map_err(|_| ProofVerificationAggModeError::EventDecoding)?; + + // Event is indexed by merkle root + let merkle_root = log.topics()[1].0; + + // Block Number shouldn't be empty, in case it is, + // there is a problem with this log, and we skip it + // This same logic is replicated for other checks. + let Some(block_number) = log.block_number else { + return Err(ProofVerificationAggModeError::EventDecoding); + }; + + let Some(block) = self + .rpc_provider + .get_block(BlockId::Number(alloy::eips::BlockNumberOrTag::Number( + block_number, + ))) + .await + .map_err(|e| ProofVerificationAggModeError::EthereumProviderError(e.to_string()))? + else { + return Err(ProofVerificationAggModeError::EventDecoding); + }; + + let Some(beacon_parent_root) = block.header.parent_beacon_block_root else { + return Err(ProofVerificationAggModeError::EventDecoding); + }; + + let Some(beacon_block) = self + .beacon_client + .get_block_header_from_parent_hash(beacon_parent_root.0) + .await + .map_err(ProofVerificationAggModeError::BeaconClient)? + else { + return Err(ProofVerificationAggModeError::EventDecoding); + }; + + let slot: u64 = beacon_block + .header + .message + .slot + .parse() + .expect("Slot to be parsable number"); + + let Some(blob_data) = self + .beacon_client + .get_blob_by_versioned_hash(slot, blob_versioned_hash) + .await + .map_err(ProofVerificationAggModeError::BeaconClient)? + else { + return Err(ProofVerificationAggModeError::EventDecoding); + }; + + let blob_bytes = + hex::decode(blob_data.blob.replace("0x", "")).expect("A valid hex encoded data"); + let proof_commitments = decoded_blob(&blob_bytes); + + Ok((merkle_root, proof_commitments)) + } +} diff --git a/aggregation_mode/sdk/src/blockchain/types.rs b/aggregation_mode/sdk/src/blockchain/types.rs new file mode 100644 index 000000000..981f90641 --- /dev/null +++ b/aggregation_mode/sdk/src/blockchain/types.rs @@ -0,0 +1,211 @@ +use crate::beacon::BeaconClientError; +use alloy::sol; +use lambdaworks_crypto::merkle_tree::traits::IsMerkleTreeBackend; +use serde::{Deserialize, Serialize}; +use sha3::{Digest, Keccak256}; + +sol!( + #[sol(rpc)] + AlignedProofAggregationService, + "abi/AlignedProofAggregationService.json" +); + +pub type AlignedProofAggregationServiceContract = + AlignedProofAggregationService::AlignedProofAggregationServiceInstance< + alloy::providers::fillers::FillProvider< + alloy::providers::fillers::JoinFill< + alloy::providers::Identity, + alloy::providers::fillers::JoinFill< + alloy::providers::fillers::GasFiller, + alloy::providers::fillers::JoinFill< + alloy::providers::fillers::BlobGasFiller, + alloy::providers::fillers::JoinFill< + alloy::providers::fillers::NonceFiller, + alloy::providers::fillers::ChainIdFiller, + >, + >, + >, + >, + alloy::providers::RootProvider, + >, + >; + +pub type RPCProvider = alloy::providers::fillers::FillProvider< + alloy::providers::fillers::JoinFill< + alloy::providers::Identity, + alloy::providers::fillers::JoinFill< + alloy::providers::fillers::GasFiller, + alloy::providers::fillers::JoinFill< + alloy::providers::fillers::BlobGasFiller, + alloy::providers::fillers::JoinFill< + alloy::providers::fillers::NonceFiller, + alloy::providers::fillers::ChainIdFiller, + >, + >, + >, + >, + alloy::providers::RootProvider, +>; + +#[repr(u16)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)] +pub enum AggregationModeProvingSystem { + SP1 = 1, + RISC0 = 2, +} + +impl AggregationModeProvingSystem { + pub const fn as_u16(self) -> u16 { + self as u16 + } + + pub const fn id(self) -> u16 { + self.as_u16() + } + + pub const fn id_bytes(self) -> [u8; 2] { + self.as_u16().to_be_bytes() + } +} + +impl TryFrom for AggregationModeProvingSystem { + type Error = (); + + fn try_from(v: u16) -> Result { + match v { + 0 => Ok(AggregationModeProvingSystem::SP1), + 1 => Ok(AggregationModeProvingSystem::RISC0), + _ => Err(()), + } + } +} + +#[derive(Debug)] +pub enum AggregationModeVerificationData { + SP1 { + vk: [u8; 32], + public_inputs: Vec, + }, + Risc0 { + image_id: [u8; 32], + public_inputs: Vec, + }, +} + +impl AggregationModeVerificationData { + pub fn program_id(&self) -> [u8; 32] { + match self { + Self::Risc0 { image_id, .. } => *image_id, + Self::SP1 { vk, .. } => *vk, + } + } + + pub fn public_inputs(&self) -> &Vec { + match self { + Self::Risc0 { public_inputs, .. } => public_inputs, + Self::SP1 { public_inputs, .. } => public_inputs, + } + } + + pub fn proving_system_id(&self) -> u16 { + match self { + Self::SP1 { .. } => AggregationModeProvingSystem::SP1.id(), + Self::Risc0 { .. } => AggregationModeProvingSystem::RISC0.id(), + } + } + + pub fn proving_system_id_bytes(&self) -> [u8; 2] { + match self { + Self::SP1 { .. } => AggregationModeProvingSystem::SP1.id_bytes(), + Self::Risc0 { .. } => AggregationModeProvingSystem::RISC0.id_bytes(), + } + } + + pub fn commitment(&self) -> [u8; 32] { + match self { + AggregationModeVerificationData::SP1 { vk, public_inputs } => { + let mut hasher = Keccak256::new(); + hasher.update(self.proving_system_id_bytes()); + hasher.update(vk); + hasher.update(public_inputs); + hasher.finalize().into() + } + AggregationModeVerificationData::Risc0 { + image_id, + public_inputs, + } => { + let mut hasher = Keccak256::new(); + hasher.update(self.proving_system_id_bytes()); + hasher.update(image_id); + hasher.update(public_inputs); + hasher.finalize().into() + } + } + } +} + +// We use a newtype wrapper around `[u8; 32]` because Rust's orphan rule +// prevents implementing a foreign trait (`IsMerkleTreeBackend`) for a foreign type (`[u8; 32]`). +#[derive(Default, Debug, PartialEq, Eq)] +pub struct Hash32(pub [u8; 32]); + +// Note: +// We define a version of the backend that takes the leaves as hashed data +// since the user may not have access to the proofs that he didn't submit +// The original MerkleTreeBackend is defined in three locations +// - aggregation_mode/src/aggregators/mod.rs +// - aggregation_mode/src/aggregators/risc0_aggregator.rs +// - aggregation_mode/src/aggregators/sp1_aggregator.rs +// The definition on aggregator/mod.rs supports taking proofs from both Risc0 and SP1 +// Hashes of all implementations should match +impl IsMerkleTreeBackend for Hash32 { + type Data = Hash32; + type Node = [u8; 32]; + + /// We don't have to hash the data, as the blob already contains the proof commitments (which represent the merkle leaves) + fn hash_data(leaf: &Self::Data) -> Self::Node { + leaf.0 + } + + /// Computes a commutative Keccak256 hash, ensuring H(a, b) == H(b, a). + /// + /// See: https://docs.openzeppelin.com/contracts/5.x/api/utils#Hashes + /// + /// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/Hashes.sol#L17-L19 + /// + /// Compliant with OpenZeppelin's `processProofCalldata` function from MerkleProof.sol. + /// + /// See: https://docs.openzeppelin.com/contracts/5.x/api/utils#MerkleProof + /// + /// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol#L114-L128 + fn hash_new_parent(child_1: &Self::Node, child_2: &Self::Node) -> Self::Node { + let mut hasher = Keccak256::new(); + if child_1 < child_2 { + hasher.update(child_1); + hasher.update(child_2); + } else { + hasher.update(child_2); + hasher.update(child_1); + } + hasher.finalize().into() + } +} + +#[derive(Debug, Clone)] +pub enum ProofVerificationAggModeError { + ProvingSystemNotSupportedInAggMode, + EthereumProviderError(String), + BeaconClient(BeaconClientError), + EventDecoding, + MerkleTreeConstruction, +} + +#[derive(Debug, Clone)] +pub enum ProofStatus { + Verified { + merkle_root: [u8; 32], + merkle_path: Vec<[u8; 32]>, + }, + Invalid, + NotFound, +} diff --git a/aggregation_mode/sdk/src/lib.rs b/aggregation_mode/sdk/src/lib.rs index 3ad15d1f1..5a02e28fd 100644 --- a/aggregation_mode/sdk/src/lib.rs +++ b/aggregation_mode/sdk/src/lib.rs @@ -1,3 +1,4 @@ +mod beacon; +pub mod blockchain; pub mod gateway; pub mod types; -// TODO: move the rest of the sdk in crates/sdk/aggregation_layer to here diff --git a/aggregation_mode/sdk/src/types.rs b/aggregation_mode/sdk/src/types.rs index ddc4949ec..a598b44c8 100644 --- a/aggregation_mode/sdk/src/types.rs +++ b/aggregation_mode/sdk/src/types.rs @@ -32,4 +32,10 @@ impl Network { Self::Devnet => "http://127.0.0.1:8089".to_string(), } } + + pub fn proof_aggregator_contract_address(&self) -> String { + match self { + Self::Devnet => "0xcbEAF3BDe82155F56486Fb5a1072cb8baAf547cc".to_string(), + } + } } From b59f572228cff7b6184dda81cdafe0092a81b52a Mon Sep 17 00:00:00 2001 From: Marcos Nicolau Date: Mon, 22 Dec 2025 18:31:18 -0300 Subject: [PATCH 2/2] wip partial move of verify on chain to agg mode cli --- aggregation_mode/cli/src/commands/helpers.rs | 28 ++++++++++++++++++++ aggregation_mode/cli/src/commands/mod.rs | 19 +++++++++++++ aggregation_mode/cli/src/commands/submit.rs | 6 ++--- aggregation_mode/cli/src/commands/verify.rs | 27 +++++++++++++++++++ aggregation_mode/cli/src/main.rs | 17 +++--------- 5 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 aggregation_mode/cli/src/commands/helpers.rs create mode 100644 aggregation_mode/cli/src/commands/verify.rs diff --git a/aggregation_mode/cli/src/commands/helpers.rs b/aggregation_mode/cli/src/commands/helpers.rs new file mode 100644 index 000000000..1fffccead --- /dev/null +++ b/aggregation_mode/cli/src/commands/helpers.rs @@ -0,0 +1,28 @@ +use clap::{self, ValueEnum}; +use std::str::FromStr; + +use agg_mode_sdk::types::Network; + +pub fn parse_network(value: &str) -> Result { + Network::from_str(value).map_err(|_| format!("unsupported network supplied: {value}")) +} + +#[derive(Debug, Clone, ValueEnum)] +pub enum ProvingSystemArg { + #[clap(name = "GnarkPlonkBls12_381")] + GnarkPlonkBls12_381, + #[clap(name = "GnarkPlonkBn254")] + GnarkPlonkBn254, + #[clap(name = "GnarkGroth16Bn254")] + GnarkGroth16Bn254, + #[clap(name = "SP1")] + SP1, + #[clap(name = "Risc0")] + Risc0, + #[clap(name = "CircomGroth16Bn256")] + CircomGroth16Bn256, + #[clap(name = "Mina")] + Mina, + #[clap(name = "MinaAccount")] + MinaAccount, +} diff --git a/aggregation_mode/cli/src/commands/mod.rs b/aggregation_mode/cli/src/commands/mod.rs index d53a5d11c..742a90e2c 100644 --- a/aggregation_mode/cli/src/commands/mod.rs +++ b/aggregation_mode/cli/src/commands/mod.rs @@ -1 +1,20 @@ +use crate::commands::{submit::SubmitCommand, verify::VerifyOnChainArgs}; +use clap::{Parser, Subcommand}; + +mod helpers; pub mod submit; +pub mod verify; + +#[derive(Debug, Parser)] +pub struct Cli { + #[command(subcommand)] + pub command: Command, +} + +#[derive(Debug, Subcommand)] +pub enum Command { + #[command(subcommand)] + Submit(SubmitCommand), + #[command(name = "verify-on-chain")] + VerifyOnChain(VerifyOnChainArgs), +} diff --git a/aggregation_mode/cli/src/commands/submit.rs b/aggregation_mode/cli/src/commands/submit.rs index 9c636f5be..41b29d66d 100644 --- a/aggregation_mode/cli/src/commands/submit.rs +++ b/aggregation_mode/cli/src/commands/submit.rs @@ -4,6 +4,8 @@ use clap::{command, Args, Subcommand}; use sp1_sdk::{SP1ProofWithPublicValues, SP1VerifyingKey}; use std::{path::PathBuf, str::FromStr}; +use crate::commands::helpers::parse_network; + #[derive(Debug, Subcommand)] pub enum SubmitCommand { #[command(name = "sp1")] @@ -22,10 +24,6 @@ pub struct SubmitSP1Args { network: Network, } -fn parse_network(value: &str) -> Result { - Network::from_str(value).map_err(|_| format!("unsupported network supplied: {value}")) -} - pub async fn run(args: SubmitSP1Args) { tracing::info!("Submitting SP1 proof to {:?} ", args.network); diff --git a/aggregation_mode/cli/src/commands/verify.rs b/aggregation_mode/cli/src/commands/verify.rs new file mode 100644 index 000000000..7e7c1ef57 --- /dev/null +++ b/aggregation_mode/cli/src/commands/verify.rs @@ -0,0 +1,27 @@ +use agg_mode_sdk::types::Network; +use clap::{self, Args}; +use std::path::PathBuf; + +use crate::commands::helpers::{parse_network, ProvingSystemArg}; + +#[derive(Debug, Clone, Args)] +pub struct VerifyOnChainArgs { + #[arg(short = 'n', long = "network", default_value = "devnet", value_parser = parse_network)] + network: Network, + #[arg(long = "rpc-url")] + rpc_url: String, + #[arg(long = "beacon-url")] + beacon_url: String, + #[arg(long = "from-block")] + from_block: Option, + #[arg(long = "proving-system")] + proving_system: ProvingSystemArg, + #[arg(name = "Program verification key hash", long = "vk", required = true)] + program_vk: PathBuf, + #[arg(long = "vk")] + verifying_key_path: PathBuf, + #[arg(name = "Public input file name", long = "public-input")] + pub_input_file_name: Option, +} + +pub async fn run(args: VerifyOnChainArgs) {} diff --git a/aggregation_mode/cli/src/main.rs b/aggregation_mode/cli/src/main.rs index d5e892105..19c70cb5d 100644 --- a/aggregation_mode/cli/src/main.rs +++ b/aggregation_mode/cli/src/main.rs @@ -1,19 +1,7 @@ -use agg_mode_cli::commands::{self, submit::SubmitCommand}; -use clap::{Parser, Subcommand}; +use agg_mode_cli::commands::{self, submit::SubmitCommand, Cli, Command}; +use clap::Parser; use tracing_subscriber::{EnvFilter, FmtSubscriber}; -#[derive(Debug, Parser)] -struct Cli { - #[command(subcommand)] - command: Command, -} - -#[derive(Debug, Subcommand)] -enum Command { - #[command(subcommand)] - Submit(SubmitCommand), -} - #[tokio::main] async fn main() { let filter = EnvFilter::new("info"); @@ -26,5 +14,6 @@ async fn main() { Command::Submit(subcommand) => match subcommand { SubmitCommand::SP1(args) => commands::submit::run(args).await, }, + Command::VerifyOnChain(args) => commands::verify::run(args).await, }; }