diff --git a/.github/workflows/build-rust.yml b/.github/workflows/build-and-test-rust.yml similarity index 61% rename from .github/workflows/build-rust.yml rename to .github/workflows/build-and-test-rust.yml index aa0132177..6aafeba9e 100644 --- a/.github/workflows/build-rust.yml +++ b/.github/workflows/build-and-test-rust.yml @@ -1,4 +1,4 @@ -name: build-rust-projects +name: build-and-test-rust-projects on: merge_group: @@ -7,13 +7,13 @@ on: pull_request: branches: ["*"] paths: - - 'batcher/**' - - '.github/workflows/build-rust.yml' + - "batcher/**" + - ".github/workflows/build-rust.yml" jobs: build: runs-on: aligned-runner - + steps: - uses: actions/checkout@v4 @@ -45,3 +45,24 @@ jobs: run: | cd batcher cargo build --all + + test: + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Cache Rust dependencies + uses: actions/cache@v3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + batcher/target + key: ${{ runner.os }}-rust-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-rust- + - name: Run tests + run: | + cd batcher + cargo test --all diff --git a/Makefile b/Makefile index 664733182..9a1575689 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ OS := $(shell uname -s) CONFIG_FILE?=config-files/config.yaml AGG_CONFIG_FILE?=config-files/config-aggregator.yaml -OPERATOR_VERSION=v0.7.3 +OPERATOR_VERSION=v0.8.0 ifeq ($(OS),Linux) BUILD_ALL_FFI = $(MAKE) build_all_ffi_linux @@ -121,6 +121,22 @@ update_operator: @make build_operator @./operator/build/aligned-operator --version +operator_valid_marshall_fuzz_macos: + @cd operator/pkg && go test -fuzz=FuzzValidMarshall -ldflags=-extldflags=-Wl,-ld_classic + +operator_valid_marshall_fuzz_linux: + @cd operator/pkg && \ + LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):$(CURDIR)/operator/risc_zero/lib \ + go test -fuzz=FuzzValidMarshall + +operator_marshall_unmarshall_fuzz_macos: + @cd operator/pkg && go test -fuzz=FuzzMarshalUnmarshal -ldflags=-extldflags=-Wl,-ld_classic + +operator_marshall_unmarshall_fuzz_linux: + @cd operator/pkg && \ + LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):$(CURDIR)/operator/risc_zero/lib \ + go test -fuzz=FuzzMarshalUnmarshal + bindings: cd contracts && ./generate-go-bindings.sh diff --git a/README.md b/README.md index f09837125..2191e59f8 100644 --- a/README.md +++ b/README.md @@ -3,190 +3,4 @@ > [!CAUTION] > To be used in testnet only. -## Table of Contents - -- [Aligned](#aligned) - - [Table of Contents](#table-of-contents) - - [The Project](#the-project) - - [How to use the testnet](#how-to-use-the-testnet) - - [Operator Guide](#operator-guide) - - [Aligned Infrastructure Guide](#aligned-infrastructure-guide) - - [Submitting Proofs to Aligned](#submitting-proofs-to-aligned) - - [Integrating Aligned into your Project](#integrating-aligned-into-your-project) - - [Versioning and Networks](#versioning-and-networks) - - -## The Project - -Aligned is a decentralized network of nodes that verifies Zero-Knowledge and Validity proofs, and post the results in Ethereum. - -These proofs can be generated and used for a tenth of the price, and with extremely low latency, allowing novel types of applications that weren't possible before in Ethereum. - -## How to use the testnet - -1. Download and install Aligned to send proofs in the testnet: - -```bash -curl -L https://raw.githubusercontent.com/yetanotherco/aligned_layer/main/batcher/aligned/install_aligned.sh | bash -``` - -2. Then run the ```source``` command that should appear in the shell. - - -3. Download an example SP1 proof file with it's ELF file using: - -```bash -curl -L https://raw.githubusercontent.com/yetanotherco/aligned_layer/main/batcher/aligned/get_proof_test_files.sh | bash -``` - -We are downloading a proof previously generated, sending it to Aligned, and retrieving the results from Ethereum Holesky testnet. Aligned is using EigenLayer to do a fast and cheap verification of more than one thousand proofs per second. - -4. Let's send the proof to be verified in Aligned: - -```bash -rm -rf ~/.aligned/aligned_verification_data/ && -aligned submit \ ---proving_system SP1 \ ---proof ~/.aligned/test_files/sp1_fibonacci.proof \ ---vm_program ~/.aligned/test_files/sp1_fibonacci.elf \ ---aligned_verification_data_path ~/.aligned/aligned_verification_data \ ---batcher_url wss://batcher.alignedlayer.com \ ---rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 -``` - -5. You should get a response like this: - -```bash -[2024-07-01T19:17:54Z WARN aligned] Missing keystore used for payment. This proof will not be included if sent to Eth Mainnet -[2024-07-01T19:17:54Z INFO aligned] Submitting proofs to the Aligned batcher... -[2024-07-01T19:19:18Z INFO aligned] Batch inclusion data written into ./aligned_verification_data/e367d76e_0.json -[2024-07-01T19:19:18Z INFO aligned] Proofs submitted to aligned. See the batch in the explorer: -[2024-07-01T19:19:18Z INFO aligned] https://explorer.alignedlayer.com/batches/0xe367d76e832edec893d3a9027b3c231b2e3994c47acfac2e67197c13c9be0c4c -``` - -You can use the link to the explorer to check the status of your transaction. - -6. After three Ethereum blocks, you can check if it has been verified with: - -```bash -aligned verify-proof-onchain \ ---aligned-verification-data ~/.aligned/aligned_verification_data/*.json \ ---rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---chain holesky \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 -``` - -This is reading the result of the verification of the proof in Ethereum. - -7. You should get this result: - -```bash -[2024-06-17T21:58:43Z INFO aligned] Your proof was verified in Aligned and included in the batch! -``` - -If the proof wasn't verified you should get this result: - -```bash -[2024-06-17T21:59:09Z INFO aligned] Your proof was not included in the batch. -``` - -Aligned works in: -- MacOS Arm64 (M1 or higher) -- Linux x86 with GLIBC_2.32 or superior (For example, Ubuntu 22.04 or higher) - If you don't meet these requirements, clone the repository, install rust, and then run: - -```bash -make uninstall_aligned -make install_aligned_compiling -``` - -### Reading the results of proof verification in Ethereum - - -#### Using CURL and an Ethereum RPC -In step 6 of the previous section, we used the `aligned verify-proof-onchain` to check that our proof was verified in Aligned. - -Internally, this is making a call to our Aligned contract, verifying commitments are right, and that the proof is included in the batch. - -That command is doing the same as the following `curl` to an Ethereum node. - -```bash -curl -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_call","id":1, "params":[{"to": "0x58F280BeBE9B34c9939C3C39e0890C81f163B623", "data": ""}]}' \ - -X POST https://ethereum-holesky-rpc.publicnode.com -``` - -This will return 0x1 if the proof and it's associated data is correct and verified in Aligned, and 0x0 if not. - -For example, this a correct calldata for a verified proof: - -```bash -curl -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_call","id":1,"params":[{"to": "0x58F280BeBE9B34c9939C3C39e0890C81f163B623", "data": "0xfa534dc0c181e470901eecf693bfa6f0e89e837dcf35700cdd91c210a0ce0660e86742080000000000000000000000000000000000000000000000000000000000000000836371a502bf5ad67be837b21fa99bc381f7e8124f02042ffb80fa7ce27bc8f6f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000007553cb14bff387c06e016cb3e7946e91d9fe44a54ad5d888ce8343ddb16116a700000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000001007b2f4966c3ab3e59d213eda057734df28c323055a2a02f50bd286585cc80128c967250f2b9ad990485338fd2d49e83f47917983f5566da551d4c32e9063ea5641d94b04bac222e06ea18cbb617d0d52c7007cc8f8b30c435b8b8101bdff0ea8482436acf251652f00397f4cefa0bb8eea1c8addb6cf2ca843004b89d80c7e1e41344fd2387535fe4afcaafde27b04543d993bbbc7286154044913e5bd65b86d7cc4d47a90132a95d9ffecb913b414ba2d2f0b1d7b826eb5025a27bcadcc0d94cb125c9c9d556eac08dd6b0f5f55f68afe699f3c529442dbf1b47e968b3705ee2e1be4acb884d184a139a390cb94e9e5806686605dc0a025269bc3afd990c8302"}]}' \ - -X POST https://ethereum-holesky-rpc.publicnode.com -``` - -To generate the calldata yourself, follow these steps: - -1. Clone the repository and move into it. -2. Create a Python virtual environment and install the dependencies with: - -```bash -python3 -m venv .aligned_venv -source .aligned_venv/bin/activate -python3 -m pip install -r examples/verify/requirements.txt -``` - -3. Encode your proof verification data with: - -```bash -python3 examples/verify/encode_verification_data.py --aligned-verification-data ~/.aligned/aligned_verification_data/*.json -``` - -If your verification data is in another path, just change the `--aligned-verification-data` parameter. - -#### Using a caller contract - -To verify a proof in your own contract, use a static call to the Aligned contract. You can use the following [Caller Contract](examples/verify/src/VerifyBatchInclusionCaller.sol) as an example. The code will look like this: - -```solidity -(bool callWasSuccessfull, bytes memory proofIsIncluded) = targetContract.staticcall( - abi.encodeWithSignature( - "verifyBatchInclusion(bytes32,bytes32,bytes32,bytes20,bytes32,bytes,uint256)", - proofCommitment, - pubInputCommitment, - provingSystemAuxDataCommitment, - proofGeneratorAddr, - batchMerkleRoot, - merkleProof, - verificationDataBatchIndex - ) -); -require(callWasSuccessfull, "static_call failed"); -``` - -## Operator Guide - -If you want to run an operator, check our [Operator Guide](./docs/operator_guides/0_running_an_operator.md). - -## Aligned Infrastructure Guide - -If you are developing on Aligned, or want to run your own devnet, check our [setup Aligned guide](docs/3_guides/6_setup_aligned.md). - - -## Submitting Proofs to Aligned -For submitting proofs generated by your own project to the network via CLI, see the documentation on [submitting proofs to Aligned](docs/3_guides/0_submitting_proofs.md). - - -## Integrating Aligned into your Project - -If you are developing applications using Aligned, we offer a [Rust-SDK](docs/3_guides/1_SDK_how_to.md) for submitting proofs directly to the network within your applications. - -## Versioning and Networks - -Testnet code and documentation is always in sync with the default [Testnet Branch](https://github.com/yetanotherco/aligned_layer/tree/feat/testnet) - -Releases are provided for each version of the testnet. - -Latest version of the code, deployed on staging network, is always on [Staging Branch](https://github.com/yetanotherco/aligned_layer/tree/feat/staging) +To learn more about Aligned and how to use it, refer to the [docs page](https://docs.alignedlayer.com/) or [docs folder](./docs/). diff --git a/aggregator/internal/pkg/aggregator.go b/aggregator/internal/pkg/aggregator.go index 477112f68..b9bb73194 100644 --- a/aggregator/internal/pkg/aggregator.go +++ b/aggregator/internal/pkg/aggregator.go @@ -67,12 +67,6 @@ type Aggregator struct { // Stores the TaskResponse for each batch by batchIdentifierHash batchDataByIdentifierHash map[[32]byte]BatchData - // Stores if an operator already submitted a response for a batch - // This is to avoid double submissions - // struct{} is used as a placeholder because it is the smallest type - // go does not have a set type - operatorRespondedBatch map[uint32]map[eigentypes.Bytes32]struct{} - // This task index is to communicate with the local BLS // Service. // Note: In case of a reboot it can start from 0 again @@ -146,7 +140,7 @@ func NewAggregator(aggregatorConfig config.AggregatorConfig) (*Aggregator, error return taskResponseDigest, nil } - operatorPubkeysService := oppubkeysserv.NewOperatorsInfoServiceInMemory(context.Background(), clients.AvsRegistryChainSubscriber, clients.AvsRegistryChainReader, nil, logger) + operatorPubkeysService := oppubkeysserv.NewOperatorsInfoServiceInMemory(context.Background(), clients.AvsRegistryChainSubscriber, clients.AvsRegistryChainReader, nil, oppubkeysserv.Opts{}, logger) avsRegistryService := avsregistry.NewAvsRegistryServiceChainCaller(avsReader.ChainReader, operatorPubkeysService, logger) blsAggregationService := blsagg.NewBlsAggregatorService(avsRegistryService, hashFunction, logger) @@ -167,7 +161,6 @@ func NewAggregator(aggregatorConfig config.AggregatorConfig) (*Aggregator, error batchesIdxByIdentifierHash: batchesIdxByIdentifierHash, batchDataByIdentifierHash: batchDataByIdentifierHash, batchCreatedBlockByIdx: batchCreatedBlockByIdx, - operatorRespondedBatch: make(map[uint32]map[eigentypes.Bytes32]struct{}), nextBatchIndex: nextBatchIndex, taskMutex: &sync.Mutex{}, walletMutex: &sync.Mutex{}, @@ -220,12 +213,6 @@ func (agg *Aggregator) handleBlsAggServiceResponse(blsAggServiceResp blsagg.BlsA agg.taskMutex.Lock() batchIdentifierHash := agg.batchesIdentifierHashByIdx[blsAggServiceResp.TaskIndex] agg.logger.Error("BlsAggregationServiceResponse contains an error", "err", blsAggServiceResp.Err, "batchIdentifierHash", hex.EncodeToString(batchIdentifierHash[:])) - agg.logger.Info("- Locking task mutex: Delete task from operator map", "taskIndex", blsAggServiceResp.TaskIndex) - - // Remove task from the list of tasks - delete(agg.operatorRespondedBatch, blsAggServiceResp.TaskIndex) - - agg.logger.Info("- Unlocking task mutex: Delete task from operator map", "taskIndex", blsAggServiceResp.TaskIndex) agg.taskMutex.Unlock() return } @@ -254,10 +241,6 @@ func (agg *Aggregator) handleBlsAggServiceResponse(blsAggServiceResp blsagg.BlsA batchIdentifierHash := agg.batchesIdentifierHashByIdx[blsAggServiceResp.TaskIndex] batchData := agg.batchDataByIdentifierHash[batchIdentifierHash] taskCreatedBlock := agg.batchCreatedBlockByIdx[blsAggServiceResp.TaskIndex] - - // Delete the task from the map - delete(agg.operatorRespondedBatch, blsAggServiceResp.TaskIndex) - agg.AggregatorConfig.BaseConfig.Logger.Info("- Unlocked Resources: Fetching merkle root") agg.taskMutex.Unlock() @@ -282,7 +265,6 @@ func (agg *Aggregator) handleBlsAggServiceResponse(blsAggServiceResp blsagg.BlsA agg.logger.Info("Aggregator successfully responded to task", "taskIndex", blsAggServiceResp.TaskIndex, "batchIdentifierHash", "0x"+hex.EncodeToString(batchIdentifierHash[:])) - return } diff --git a/aggregator/internal/pkg/server.go b/aggregator/internal/pkg/server.go index c98ad3248..873259ecb 100644 --- a/aggregator/internal/pkg/server.go +++ b/aggregator/internal/pkg/server.go @@ -7,8 +7,6 @@ import ( "net/rpc" "time" - eigentypes "github.com/Layr-Labs/eigensdk-go/types" - "github.com/yetanotherco/aligned_layer/core/types" ) @@ -74,26 +72,6 @@ func (agg *Aggregator) ProcessOperatorSignedTaskResponseV2(signedTaskResponse *t return nil } - // Note: we already have lock here - agg.logger.Debug("- Checking if operator already responded") - batchResponses, ok := agg.operatorRespondedBatch[taskIndex] - if !ok { - batchResponses = make(map[eigentypes.Bytes32]struct{}) - agg.operatorRespondedBatch[taskIndex] = batchResponses - } - - if _, ok := batchResponses[signedTaskResponse.OperatorId]; ok { - *reply = 0 - agg.logger.Warn("Operator already responded, ignoring", - "operatorId", hex.EncodeToString(signedTaskResponse.OperatorId[:]), - "taskIndex", taskIndex, "batchMerkleRoot", hex.EncodeToString(signedTaskResponse.BatchMerkleRoot[:])) - - agg.taskMutex.Unlock() - return nil - } - - batchResponses[signedTaskResponse.OperatorId] = struct{}{} - // Don't wait infinitely if it can't answer // Create a context with a timeout of 5 seconds ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) @@ -111,9 +89,7 @@ func (agg *Aggregator) ProcessOperatorSignedTaskResponseV2(signedTaskResponse *t if err != nil { agg.logger.Warnf("BLS aggregation service error: %s", err) - // remove operator from the list of operators that responded - // so that it can try again - delete(batchResponses, signedTaskResponse.OperatorId) + // todo shouldn't we here close the channel with a reply = 1? } else { agg.logger.Info("BLS process succeeded") } diff --git a/batcher/Cargo.lock b/batcher/Cargo.lock index ebef1321f..3935d562a 100644 --- a/batcher/Cargo.lock +++ b/batcher/Cargo.lock @@ -25,13 +25,19 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.24.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "adler2" version = "2.0.0" @@ -125,6 +131,7 @@ name = "aligned-sdk" version = "0.1.0" dependencies = [ "ciborium", + "dialoguer", "ethers 2.0.14 (git+https://github.com/yetanotherco/ethers-rs.git?tag=v2.0.15-fix-reconnections)", "futures-util", "hex", @@ -169,9 +176,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.8" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26154390b1d205a4a7ac7352aa2eb4f81f391399d4e2f546fb81a2f8bb383f62" +checksum = "a43b18702501396fa9bcdeecd533bc85fac75150d308fc0f6800a01e6234a003" dependencies = [ "arrayvec", "bytes", @@ -200,7 +207,7 @@ dependencies = [ "alloy-sol-macro-input", "const-hex", "heck", - "indexmap 2.5.0", + "indexmap 2.2.6", "proc-macro-error", "proc-macro2", "quote", @@ -262,9 +269,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", @@ -277,33 +284,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -311,9 +318,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "ark-bn254" @@ -395,7 +402,7 @@ dependencies = [ "num-bigint 0.4.6", "num-traits", "paste", - "rustc_version 0.4.1", + "rustc_version 0.4.0", "zeroize", ] @@ -551,15 +558,15 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.9" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "ascii-canvas" @@ -589,7 +596,7 @@ checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" dependencies = [ "futures", "pharos", - "rustc_version 0.4.1", + "rustc_version 0.4.0", ] [[package]] @@ -611,9 +618,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-config" @@ -680,7 +687,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "tracing", - "uuid 1.10.0", + "uuid 1.9.1", ] [[package]] @@ -912,9 +919,9 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "http-body 1.0.1", + "http-body 1.0.0", "httparse", - "hyper 0.14.30", + "hyper 0.14.29", "hyper-rustls 0.24.2", "once_cell", "pin-project-lite", @@ -954,7 +961,7 @@ dependencies = [ "http 0.2.12", "http 1.1.0", "http-body 0.4.6", - "http-body 1.0.1", + "http-body 1.0.0", "http-body-util", "itoa", "num-integer", @@ -986,7 +993,7 @@ dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", "aws-smithy-types", - "rustc_version 0.4.1", + "rustc_version 0.4.0", "tracing", ] @@ -1001,9 +1008,9 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.1", + "http-body 1.0.0", "http-body-util", - "hyper 1.4.1", + "hyper 1.4.0", "hyper-util", "itoa", "matchit", @@ -1026,20 +1033,20 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.1", + "http-body 1.0.0", "http-body-util", "mime", "pin-project-lite", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", "tracing", @@ -1047,18 +1054,18 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", + "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", "serde", - "windows-targets 0.52.6", ] [[package]] @@ -1139,7 +1146,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash 1.1.0", + "rustc-hash", "shlex", "syn 2.0.77", "which", @@ -1201,21 +1208,21 @@ checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" dependencies = [ "arrayref", "arrayvec", - "constant_time_eq 0.3.1", + "constant_time_eq 0.3.0", ] [[package]] name = "blake3" -version = "1.5.4" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", - "constant_time_eq 0.3.1", - "rayon-core", + "constant_time_eq 0.3.0", + "rayon", ] [[package]] @@ -1275,18 +1282,18 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.7.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" +checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" dependencies = [ "proc-macro2", "quote", @@ -1341,9 +1348,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.9" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" dependencies = [ "serde", ] @@ -1460,9 +1467,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.17" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" +checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc" dependencies = [ "clap_builder", "clap_derive", @@ -1470,9 +1477,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.17" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" +checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99" dependencies = [ "anstream", "anstyle", @@ -1494,9 +1501,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "cobs" @@ -1558,9 +1565,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "console" @@ -1577,9 +1584,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.12.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" +checksum = "0121754e84117e65f9d90648ee6aa4882a6e63110307ab73967a4c5e7e69e586" dependencies = [ "cfg-if", "cpufeatures", @@ -1602,9 +1609,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "constant_time_eq" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "convert_case" @@ -1624,15 +1631,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.7" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -1643,7 +1650,7 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47" dependencies = [ - "rustc_version 0.4.1", + "rustc_version 0.4.0", ] [[package]] @@ -1739,7 +1746,7 @@ dependencies = [ "cpufeatures", "curve25519-dalek-derive", "fiat-crypto", - "rustc_version 0.4.1", + "rustc_version 0.4.0", "subtle", "zeroize", ] @@ -1757,9 +1764,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.10" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" dependencies = [ "darling_core", "darling_macro", @@ -1767,9 +1774,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" dependencies = [ "fnv", "ident_case", @@ -1781,9 +1788,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", @@ -1846,10 +1853,23 @@ dependencies = [ "convert_case", "proc-macro2", "quote", - "rustc_version 0.4.1", + "rustc_version 0.4.0", "syn 2.0.77", ] +[[package]] +name = "dialoguer" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" +dependencies = [ + "console", + "shell-words", + "tempfile", + "thiserror", + "zeroize", +] + [[package]] name = "digest" version = "0.9.0" @@ -1927,9 +1947,9 @@ checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "dunce" -version = "1.0.5" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "ecdsa" @@ -2014,12 +2034,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" -[[package]] -name = "embedded-io" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" - [[package]] name = "ena" version = "0.14.3" @@ -2064,9 +2078,9 @@ dependencies = [ [[package]] name = "env_filter" -version = "0.1.2" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" dependencies = [ "log", "regex", @@ -2074,9 +2088,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.5" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" dependencies = [ "anstream", "anstyle", @@ -2351,7 +2365,7 @@ dependencies = [ "ethabi", "generic-array 0.14.7", "k256", - "num_enum 0.7.3", + "num_enum 0.7.2", "once_cell", "open-fastrlp", "rand", @@ -2380,7 +2394,7 @@ dependencies = [ "ethabi", "generic-array 0.14.7", "k256", - "num_enum 0.7.3", + "num_enum 0.7.2", "once_cell", "open-fastrlp", "rand", @@ -2615,9 +2629,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fastrlp" @@ -2701,7 +2715,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -2908,15 +2922,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "git2" -version = "0.19.0" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" +checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" dependencies = [ "bitflags 2.6.0", "libc", @@ -2978,7 +2992,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.5.0", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -2987,9 +3001,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.6" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" dependencies = [ "atomic-waker", "bytes", @@ -2997,7 +3011,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap 2.5.0", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -3149,9 +3163,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ "bytes", "http 1.1.0", @@ -3166,15 +3180,15 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.1", + "http-body 1.0.0", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -3190,9 +3204,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" dependencies = [ "bytes", "futures-channel", @@ -3214,16 +3228,16 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "c4fe55fb7a772d59a5ff1dfbff4fe0258d19b89fec4b233e75d35d5d2316badc" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.6", + "h2 0.4.5", "http 1.1.0", - "http-body 1.0.1", + "http-body 1.0.0", "httparse", "httpdate", "itoa", @@ -3241,7 +3255,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.30", + "hyper 0.14.29", "log", "rustls 0.21.12", "rustls-native-certs", @@ -3251,15 +3265,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.3" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.4.1", + "hyper 1.4.0", "hyper-util", - "rustls 0.23.13", + "rustls 0.23.11", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -3275,7 +3289,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.4.1", + "hyper 1.4.0", "hyper-util", "native-tls", "tokio", @@ -3293,8 +3307,8 @@ dependencies = [ "futures-channel", "futures-util", "http 1.1.0", - "http-body 1.0.1", - "hyper 1.4.1", + "http-body 1.0.0", + "hyper 1.4.0", "pin-project-lite", "socket2", "tokio", @@ -3305,9 +3319,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3399,9 +3413,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.5", @@ -3441,15 +3455,15 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.10.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" [[package]] name = "itertools" @@ -3495,18 +3509,18 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -3541,9 +3555,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", "ecdsa 0.16.9", @@ -3564,9 +3578,9 @@ dependencies = [ [[package]] name = "keccak-asm" -version = "0.1.4" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +checksum = "47a3633291834c4fbebf8673acbc1b04ec9d151418ff9b8e26dcd79129928758" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -3585,7 +3599,7 @@ dependencies = [ "lalrpop-util", "petgraph", "regex", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", "string_cache", "term", "tiny-keccak", @@ -3599,7 +3613,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" dependencies = [ - "regex-automata 0.4.7", + "regex-automata 0.4.8", ] [[package]] @@ -3647,9 +3661,9 @@ checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libgit2-sys" -version = "0.17.0+1.8.1" +version = "0.16.2+1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224" +checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8" dependencies = [ "cc", "libc", @@ -3659,9 +3673,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", "windows-targets 0.52.6", @@ -3685,9 +3699,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.20" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" dependencies = [ "cc", "libc", @@ -3719,9 +3733,9 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" -version = "0.12.4" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ "hashbrown 0.14.5", ] @@ -3775,6 +3789,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + [[package]] name = "miniz_oxide" version = "0.8.0" @@ -3786,14 +3809,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ - "hermit-abi", "libc", "wasi", - "windows-sys 0.52.0", + "windows-sys 0.48.0", ] [[package]] @@ -3966,11 +3988,11 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.3" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" dependencies = [ - "num_enum_derive 0.7.3", + "num_enum_derive 0.7.2", ] [[package]] @@ -3987,11 +4009,11 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.3" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate 3.2.0", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 2.0.77", @@ -4014,18 +4036,21 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.36.4" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] [[package]] name = "oneshot" @@ -4060,9 +4085,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -4092,9 +4117,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -4431,7 +4456,7 @@ version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 3.2.0", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -4568,7 +4593,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.5.0", + "indexmap 2.2.6", ] [[package]] @@ -4578,7 +4603,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" dependencies = [ "futures", - "rustc_version 0.4.1", + "rustc_version 0.4.0", ] [[package]] @@ -4686,9 +4711,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "portable-atomic" @@ -4698,13 +4723,12 @@ checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" [[package]] name = "postcard" -version = "1.0.10" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" dependencies = [ "cobs", - "embedded-io 0.4.0", - "embedded-io 0.6.1", + "embedded-io", "serde", ] @@ -4716,12 +4740,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "precomputed-hash" @@ -4731,9 +4752,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "prettyplease" -version = "0.2.22" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", "syn 2.0.77", @@ -4755,13 +4776,13 @@ dependencies = [ [[package]] name = "priority-queue" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560bcab673ff7f6ca9e270c17bf3affd8a05e3bd9207f123b0d45076fd8197e8" +checksum = "714c75db297bc88a63783ffc6ab9f830698a6705aa0201416931759ef4c8183d" dependencies = [ "autocfg", "equivalent", - "indexmap 2.5.0", + "indexmap 2.2.6", ] [[package]] @@ -4776,11 +4797,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.2.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_edit 0.22.21", + "toml_edit 0.21.1", ] [[package]] @@ -4830,7 +4851,7 @@ dependencies = [ "rand", "rand_chacha", "rand_xorshift", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", "rusty-fork", "tempfile", "unarray", @@ -4861,9 +4882,9 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.23" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" dependencies = [ "cc", ] @@ -4876,17 +4897,16 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quinn" -version = "0.11.5" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" dependencies = [ "bytes", "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.0.0", - "rustls 0.23.13", - "socket2", + "rustc-hash", + "rustls 0.23.11", "thiserror", "tokio", "tracing", @@ -4894,15 +4914,15 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.8" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" dependencies = [ "bytes", "rand", "ring 0.17.8", - "rustc-hash 2.0.0", - "rustls 0.23.13", + "rustc-hash", + "rustls 0.23.11", "slab", "thiserror", "tinyvec", @@ -4911,22 +4931,22 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.5" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" dependencies = [ "libc", "once_cell", "socket2", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] name = "quote" -version = "1.0.37" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -5016,9 +5036,9 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.6" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom", "libredox", @@ -5033,8 +5053,8 @@ checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -5048,13 +5068,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -5071,9 +5091,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" @@ -5089,7 +5109,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.30", + "hyper 0.14.29", "hyper-rustls 0.24.2", "ipnet", "js-sys", @@ -5128,12 +5148,12 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.6", + "h2 0.4.5", "http 1.1.0", - "http-body 1.0.1", + "http-body 1.0.0", "http-body-util", - "hyper 1.4.1", - "hyper-rustls 0.27.3", + "hyper 1.4.0", + "hyper-rustls 0.27.2", "hyper-tls", "hyper-util", "ipnet", @@ -5145,7 +5165,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.13", + "rustls 0.23.11", "rustls-pemfile 2.1.3", "rustls-pki-types", "serde", @@ -5169,9 +5189,9 @@ dependencies = [ [[package]] name = "reqwest-middleware" -version = "0.3.3" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562ceb5a604d3f7c885a792d42c199fd8af239d0a51b2fa6a78aafa092452b04" +checksum = "39346a33ddfe6be00cbc17a34ce996818b97b230b87229f10114693becca1268" dependencies = [ "anyhow", "async-trait", @@ -5476,12 +5496,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" -[[package]] -name = "rustc-hash" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" - [[package]] name = "rustc-hex" version = "2.1.0" @@ -5499,18 +5513,18 @@ dependencies = [ [[package]] name = "rustc_version" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ "semver 1.0.23", ] [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.6.0", "errno", @@ -5533,14 +5547,14 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.13" +version = "0.23.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" dependencies = [ "once_cell", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.8", + "rustls-webpki 0.102.5", "subtle", "zeroize", ] @@ -5594,9 +5608,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.8" +version = "0.102.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" dependencies = [ "ring 0.17.8", "rustls-pki-types", @@ -5663,7 +5677,7 @@ version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 3.2.0", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -5680,11 +5694,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.24" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -5751,9 +5765,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ "bitflags 2.6.0", "core-foundation", @@ -5813,18 +5827,18 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", @@ -5833,12 +5847,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "itoa", - "memchr", "ryu", "serde", ] @@ -5895,7 +5908,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.5.0", + "indexmap 2.2.6", "serde", "serde_derive", "serde_json", @@ -5921,7 +5934,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.2.6", "itoa", "ryu", "serde", @@ -5987,9 +6000,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.4" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" dependencies = [ "cc", "cfg-if", @@ -6004,6 +6017,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "shlex" version = "1.3.0" @@ -6456,15 +6475,15 @@ dependencies = [ [[package]] name = "stacker" -version = "0.1.17" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b" +checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" dependencies = [ "cc", "cfg-if", "libc", "psm", - "windows-sys 0.59.0", + "winapi", ] [[package]] @@ -6774,27 +6793,28 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", "libc", "mio", + "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", @@ -6827,7 +6847,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.13", + "rustls 0.23.11", "rustls-pki-types", "tokio", ] @@ -6868,7 +6888,7 @@ dependencies = [ "futures-util", "log", "native-tls", - "rustls 0.23.13", + "rustls 0.23.11", "rustls-pki-types", "tokio", "tokio-native-tls", @@ -6879,9 +6899,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", @@ -6892,21 +6912,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.19" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.21", + "toml_edit 0.22.15", ] [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] @@ -6917,18 +6937,29 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.2.6", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.6", "toml_datetime", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.22.21" +version = "0.22.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" +checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -6953,15 +6984,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.3" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" [[package]] name = "tower-service" -version = "0.3.3" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" @@ -7116,7 +7147,7 @@ dependencies = [ "log", "native-tls", "rand", - "rustls 0.23.13", + "rustls 0.23.11", "rustls-pki-types", "sha1", "thiserror", @@ -7135,7 +7166,7 @@ dependencies = [ "futures", "http 1.1.0", "http-body-util", - "hyper 1.4.1", + "hyper 1.4.0", "prost", "reqwest 0.12.7", "serde", @@ -7154,9 +7185,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "uint" @@ -7184,9 +7215,9 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -7199,9 +7230,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" @@ -7268,9 +7299,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.10.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" [[package]] name = "valuable" @@ -7286,9 +7317,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vergen" -version = "8.3.2" +version = "8.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2990d9ea5967266ea0ccf413a4aa5c42a93dbcfda9cb49a97de6931726b12566" +checksum = "e27d6bdd219887a9eadd19e1c34f32e47fa332301184935c6d9bca26f3cca525" dependencies = [ "anyhow", "cfg-if", @@ -7299,9 +7330,9 @@ dependencies = [ [[package]] name = "version_check" -version = "0.9.5" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vsimd" @@ -7345,20 +7376,19 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", - "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -7371,9 +7401,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -7383,9 +7413,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7393,9 +7423,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", @@ -7406,15 +7436,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-streams" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" dependencies = [ "futures-util", "js-sys", @@ -7425,9 +7455,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -7488,11 +7518,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -7737,7 +7767,7 @@ dependencies = [ "js-sys", "log", "pharos", - "rustc_version 0.4.1", + "rustc_version 0.4.0", "send_wrapper 0.6.0", "thiserror", "wasm-bindgen", @@ -7772,7 +7802,6 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ - "byteorder", "zerocopy-derive", ] @@ -7875,9 +7904,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.13+zstd.1.5.6" +version = "2.0.12+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13" dependencies = [ "cc", "pkg-config", diff --git a/batcher/aligned-batcher/gnark/go.mod b/batcher/aligned-batcher/gnark/go.mod index adeb1dc98..884fa3b71 100644 --- a/batcher/aligned-batcher/gnark/go.mod +++ b/batcher/aligned-batcher/gnark/go.mod @@ -1,28 +1,30 @@ module verifier -go 1.22.3 + go 1.22.3 -require ( - github.com/consensys/gnark v0.11.0 - github.com/consensys/gnark-crypto v0.14.0 -) + require ( + github.com/consensys/gnark v0.10.0 + github.com/consensys/gnark-crypto v0.12.2-0.20240215234832-d72fcb379d3e + ) -require ( - github.com/bits-and-blooms/bitset v1.14.2 // indirect - github.com/blang/semver/v4 v4.0.0 // indirect - github.com/consensys/bavard v0.1.13 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect - github.com/ingonyama-zk/icicle v1.1.0 // indirect - github.com/ingonyama-zk/iciclegnark v0.1.0 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mmcloughlin/addchain v0.4.0 // indirect - github.com/ronanh/intcomp v1.1.0 // indirect - github.com/rs/zerolog v1.33.0 // indirect - github.com/x448/float16 v0.8.4 // indirect - golang.org/x/crypto v0.26.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.24.0 // indirect - rsc.io/tmplfunc v0.0.3 // indirect -) + require ( + github.com/bits-and-blooms/bitset v1.8.0 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fxamacker/cbor/v2 v2.5.0 // indirect + github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect + github.com/ingonyama-zk/icicle v0.0.0-20230928131117-97f0079e5c71 // indirect + github.com/ingonyama-zk/iciclegnark v0.1.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rs/zerolog v1.30.0 // indirect + github.com/stretchr/testify v1.8.4 // indirect + github.com/x448/float16 v0.8.4 // indirect + golang.org/x/sync v0.3.0 // indirect + golang.org/x/sys v0.15.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + rsc.io/tmplfunc v0.0.3 // indirect + ) diff --git a/batcher/aligned-batcher/gnark/go.sum b/batcher/aligned-batcher/gnark/go.sum index f639c2dcc..c06612d60 100644 --- a/batcher/aligned-batcher/gnark/go.sum +++ b/batcher/aligned-batcher/gnark/go.sum @@ -1,60 +1,69 @@ -github.com/bits-and-blooms/bitset v1.14.2 h1:YXVoyPndbdvcEVcseEovVfp0qjJp7S+i5+xgp/Nfbdc= -github.com/bits-and-blooms/bitset v1.14.2/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= +github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark v0.11.0 h1:YlndnlbRAoIEA+aIIHzNIW4P0dCIOM9/jCVzsXf356c= -github.com/consensys/gnark v0.11.0/go.mod h1:2LbheIOxsBI1a9Ck1XxUoy6PRnH28mSI9qrvtN2HwDY= -github.com/consensys/gnark-crypto v0.14.0 h1:DDBdl4HaBtdQsq/wfMwJvZNE80sHidrK3Nfrefatm0E= -github.com/consensys/gnark-crypto v0.14.0/go.mod h1:CU4UijNPsHawiVGNxe9co07FkzCeWHHrb1li/n1XoU0= +github.com/consensys/gnark v0.10.0 h1:yhi6ThoeFP7WrH8zQDaO56WVXe9iJEBSkfrZ9PZxabw= +github.com/consensys/gnark v0.10.0/go.mod h1:VJU5JrrhZorbfDH+EUjcuFWr2c5z19tHPh8D6KVQksU= +github.com/consensys/gnark-crypto v0.12.2-0.20240215234832-d72fcb379d3e h1:MKdOuCiy2DAX1tMp2YsmtNDaqdigpY6B5cZQDJ9BvEo= +github.com/consensys/gnark-crypto v0.12.2-0.20240215234832-d72fcb379d3e/go.mod h1:wKqwsieaKPThcFkHe0d0zMsbHEUWFmZcG7KBCse210o= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE= +github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= -github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo= +github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/ingonyama-zk/icicle v1.1.0 h1:a2MUIaF+1i4JY2Lnb961ZMvaC8GFs9GqZgSnd9e95C8= -github.com/ingonyama-zk/icicle v1.1.0/go.mod h1:kAK8/EoN7fUEmakzgZIYdWy1a2rBnpCaZLqSHwZWxEk= +github.com/ingonyama-zk/icicle v0.0.0-20230928131117-97f0079e5c71 h1:YxI1RTPzpFJ3MBmxPl3Bo0F7ume7CmQEC1M9jL6CT94= +github.com/ingonyama-zk/icicle v0.0.0-20230928131117-97f0079e5c71/go.mod h1:kAK8/EoN7fUEmakzgZIYdWy1a2rBnpCaZLqSHwZWxEk= github.com/ingonyama-zk/iciclegnark v0.1.0 h1:88MkEghzjQBMjrYRJFxZ9oR9CTIpB8NG2zLeCJSvXKQ= github.com/ingonyama-zk/iciclegnark v0.1.0/go.mod h1:wz6+IpyHKs6UhMMoQpNqz1VY+ddfKqC/gRwR/64W6WU= -github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= -github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/ronanh/intcomp v1.1.0 h1:i54kxmpmSoOZFcWPMWryuakN0vLxLswASsGa07zkvLU= -github.com/ronanh/intcomp v1.1.0/go.mod h1:7FOLy3P3Zj3er/kVrU/pl+Ql7JFZj7bwliMGketo0IU= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= -github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= +github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/batcher/aligned-batcher/gnark/verifier.go b/batcher/aligned-batcher/gnark/verifier.go index 4acba01a8..7e4fe547f 100644 --- a/batcher/aligned-batcher/gnark/verifier.go +++ b/batcher/aligned-batcher/gnark/verifier.go @@ -15,15 +15,21 @@ import "C" import ( "bytes" + "log" + "unsafe" + "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/backend/plonk" "github.com/consensys/gnark/backend/witness" - "log" - "unsafe" ) func listRefToBytes(listRef C.ListRef) []byte { + + if listRef.len == 0 { + return []byte{} + } + return C.GoBytes(unsafe.Pointer(listRef.ptr), C.int(listRef.len)) } diff --git a/batcher/aligned-batcher/src/connection.rs b/batcher/aligned-batcher/src/connection.rs new file mode 100644 index 000000000..65bbcf384 --- /dev/null +++ b/batcher/aligned-batcher/src/connection.rs @@ -0,0 +1,68 @@ +use std::sync::Arc; + +use aligned_sdk::{ + communication::serialization::cbor_serialize, + core::types::{BatchInclusionData, ResponseMessage, VerificationCommitmentBatch}, +}; +use futures_util::{stream::SplitSink, SinkExt}; +use lambdaworks_crypto::merkle_tree::merkle::MerkleTree; +use log::{error, info}; +use serde::Serialize; +use tokio::{net::TcpStream, sync::RwLock}; +use tokio_tungstenite::{ + tungstenite::{Error, Message}, + WebSocketStream, +}; + +use crate::types::{batch_queue::BatchQueueEntry, errors::BatcherError}; + +pub(crate) type WsMessageSink = Arc, Message>>>; + +pub(crate) async fn send_batch_inclusion_data_responses( + finalized_batch: Vec, + batch_merkle_tree: &MerkleTree, +) -> Result<(), BatcherError> { + for (vd_batch_idx, entry) in finalized_batch.iter().enumerate() { + let batch_inclusion_data = BatchInclusionData::new(vd_batch_idx, batch_merkle_tree); + let response = ResponseMessage::BatchInclusionData(batch_inclusion_data); + + let serialized_response = cbor_serialize(&response) + .map_err(|e| BatcherError::SerializationError(e.to_string()))?; + + let Some(ws_sink) = entry.messaging_sink.as_ref() else { + return Err(BatcherError::WsSinkEmpty); + }; + + let sending_result = ws_sink + .write() + .await + .send(Message::binary(serialized_response)) + .await; + + match sending_result { + Err(Error::AlreadyClosed) => (), + Err(e) => error!("Error while sending batch inclusion data response: {}", e), + Ok(_) => (), + } + + info!("Response sent"); + } + + Ok(()) +} + +pub(crate) async fn send_message(ws_conn_sink: WsMessageSink, message: T) { + match cbor_serialize(&message) { + Ok(serialized_response) => { + if let Err(err) = ws_conn_sink + .write() + .await + .send(Message::binary(serialized_response)) + .await + { + error!("Error while sending message: {}", err) + } + } + Err(e) => error!("Error while serializing message: {}", e), + } +} diff --git a/batcher/aligned-batcher/src/lib.rs b/batcher/aligned-batcher/src/lib.rs index 04a96f307..21a5e9623 100644 --- a/batcher/aligned-batcher/src/lib.rs +++ b/batcher/aligned-batcher/src/lib.rs @@ -3,12 +3,13 @@ extern crate core; use aligned_sdk::communication::serialization::{cbor_deserialize, cbor_serialize}; use aligned_sdk::eth::batcher_payment_service::SignatureData; use config::NonPayingConfig; +use connection::{send_message, WsMessageSink}; use dotenvy::dotenv; use ethers::contract::ContractError; use ethers::signers::Signer; -use serde::Serialize; +use types::batch_state::BatchState; +use types::user_state::UserState; -use std::collections::hash_map::Entry; use std::collections::HashMap; use std::env; use std::iter::repeat; @@ -16,30 +17,28 @@ use std::net::SocketAddr; use std::sync::Arc; use aligned_sdk::core::types::{ - BatchInclusionData, ClientMessage, NoncedVerificationData, ResponseMessage, - ValidityResponseMessage, VerificationCommitmentBatch, VerificationData, - VerificationDataCommitment, + ClientMessage, NoncedVerificationData, ResponseMessage, ValidityResponseMessage, + VerificationCommitmentBatch, VerificationData, VerificationDataCommitment, }; use aws_sdk_s3::client::Client as S3Client; use eth::{try_create_new_task, BatcherPaymentService, CreateNewTaskFeeParams, SignerMiddlewareT}; use ethers::prelude::{Middleware, Provider}; use ethers::providers::Ws; use ethers::types::{Address, Signature, TransactionReceipt, U256}; -use futures_util::stream::SplitSink; use futures_util::{future, SinkExt, StreamExt, TryStreamExt}; use lambdaworks_crypto::merkle_tree::merkle::MerkleTree; use lambdaworks_crypto::merkle_tree::traits::IsMerkleTreeBackend; use log::{debug, error, info, warn}; use tokio::net::{TcpListener, TcpStream}; -use tokio::sync::{Mutex, RwLock}; +use tokio::sync::{Mutex, MutexGuard, RwLock}; use tokio_tungstenite::tungstenite::{Error, Message}; -use tokio_tungstenite::WebSocketStream; -use types::batch_queue::{self, BatchQueue, BatchQueueEntry, BatchQueueEntryPriority}; +use types::batch_queue::{self, BatchQueueEntry, BatchQueueEntryPriority}; use types::errors::{BatcherError, BatcherSendError}; use crate::config::{ConfigFromYaml, ContractDeploymentOutput}; mod config; +mod connection; mod eth; pub mod gnark; pub mod risc_zero; @@ -62,137 +61,6 @@ const RESPOND_TO_TASK_FEE_LIMIT_DIVIDER: u128 = 2; const DEFAULT_AGGREGATOR_FEE_MULTIPLIER: u128 = 3; // to set the feeForAggregator variable higher than what was calculated const DEFAULT_AGGREGATOR_FEE_DIVIDER: u128 = 2; -struct BatchState { - batch_queue: BatchQueue, - user_nonces: HashMap, - /// The minimum fee of a pending proof for a user. - /// This should always be the fee of the biggest pending nonce by the user. - /// This is used to check if a user is submitting a proof with a higher nonce and higher fee, - /// which is invalid and should be rejected. - user_min_fee: HashMap, - user_proof_count_in_batch: HashMap, -} - -impl BatchState { - fn new() -> Self { - Self { - batch_queue: BatchQueue::new(), - user_nonces: HashMap::new(), - user_min_fee: HashMap::new(), - user_proof_count_in_batch: HashMap::new(), - } - } - - fn get_user_proof_count(&self, addr: &Address) -> u64 { - *self.user_proof_count_in_batch.get(addr).unwrap_or(&0) - } - - /* - Increments the user proof count in the batch, if the user is already in the hashmap. - If the user is not in the hashmap, it adds the user to the hashmap with a count of 1 to represent the first proof. - */ - fn increment_user_proof_count(&mut self, addr: &Address) { - self.user_proof_count_in_batch - .entry(*addr) - .and_modify(|count| *count += 1) - .or_insert(1); - } - - fn get_entry(&self, sender: Address, nonce: U256) -> Option<&BatchQueueEntry> { - self.batch_queue - .iter() - .map(|(entry, _)| entry) - .find(|entry| entry.sender == sender && entry.nonced_verification_data.nonce == nonce) - } - - /// Checks if the entry is valid - /// An entry is valid if there is no entry with the same sender, - /// lower nonce and a lower fee - /// If the entry is valid, it replaces the entry in the queue - /// to increment the max fee, then it updates the user min fee if necessary - /// If the entry is invalid, it returns a validity response message. - /// If the entry is valid, it returns None. - fn validate_and_increment_max_fee( - &mut self, - replacement_entry: BatchQueueEntry, - ) -> Option { - let replacement_max_fee = replacement_entry.nonced_verification_data.max_fee; - let nonce = replacement_entry.nonced_verification_data.nonce; - let sender = replacement_entry.sender; - - debug!( - "Checking validity of entry with sender: {:?}, nonce: {:?}, max_fee: {:?}", - sender, nonce, replacement_max_fee - ); - - // it is a valid entry only if there is no entry with the same sender, lower nonce and a lower fee - let is_valid = !self.batch_queue.iter().any(|(entry, _)| { - entry.sender == sender - && entry.nonced_verification_data.nonce < nonce - && entry.nonced_verification_data.max_fee < replacement_max_fee - }); - - if !is_valid { - return Some(ValidityResponseMessage::InvalidReplacementMessage); - } - - info!( - "Entry is valid, incrementing fee for sender: {:?}, nonce: {:?}, max_fee: {:?}", - sender, nonce, replacement_max_fee - ); - - // remove the old entry and insert the new one - // note that the entries are considered equal for the priority queue - // if they have the same nonce and sender, so we can remove the old entry - // by calling remove with the new entry - self.batch_queue.remove(&replacement_entry); - self.batch_queue.push( - replacement_entry.clone(), - BatchQueueEntryPriority::new(replacement_max_fee, nonce), - ); - - let user_min_fee = self - .batch_queue - .iter() - .filter(|(e, _)| e.sender == sender) - .map(|(e, _)| e.nonced_verification_data.max_fee) - .min() - .unwrap_or(U256::max_value()); - - self.user_min_fee.insert(sender, user_min_fee); - - None - } - - /// Updates: - /// * The user proof count in batch - /// * The user min fee pending in batch (which is the one with the highest nonce) - /// based on whats currenlty in the batch queue. - /// This is necessary because the whole batch may not be included in the finalized batch, - /// This caches are needed to validate user messages. - fn update_user_proofs_in_batch_and_min_fee(&mut self) { - let mut updated_user_min_fee = HashMap::new(); - let mut updated_user_proof_count_in_batch = HashMap::new(); - - for (entry, _) in self.batch_queue.iter() { - *updated_user_proof_count_in_batch - .entry(entry.sender) - .or_insert(0) += 1; - - let min_fee = updated_user_min_fee - .entry(entry.sender) - .or_insert(entry.nonced_verification_data.max_fee); - - if entry.nonced_verification_data.max_fee < *min_fee { - *min_fee = entry.nonced_verification_data.max_fee; - } - } - - self.user_proof_count_in_batch = updated_user_proof_count_in_batch; - self.user_min_fee = updated_user_min_fee; - } -} - pub struct Batcher { s3_client: S3Client, s3_bucket_name: String, @@ -295,10 +163,27 @@ impl Batcher { .await .expect("Failed to get fallback Batcher Payment Service contract"); + let mut user_states = HashMap::new(); + let mut batch_state = BatchState::new(); let non_paying_config = if let Some(non_paying_config) = config.batcher.non_paying { warn!("Non-paying address configuration detected. Will replace non-paying address {} with configured address.", non_paying_config.address); - Some(NonPayingConfig::from_yaml_config(non_paying_config).await) + + let non_paying_config = NonPayingConfig::from_yaml_config(non_paying_config).await; + let nonpaying_nonce = payment_service + .user_nonces(non_paying_config.replacement.address()) + .call() + .await + .expect("Could not get non-paying nonce from Ethereum"); + + let non_paying_user_state = UserState::new(nonpaying_nonce); + user_states.insert( + non_paying_config.replacement.address(), + non_paying_user_state, + ); + + batch_state = BatchState::new_with_user_states(user_states); + Some(non_paying_config) } else { None }; @@ -312,7 +197,6 @@ impl Batcher { chain_id, payment_service, payment_service_fallback, - batch_state: Mutex::new(BatchState::new()), max_block_interval: config.batcher.block_interval, min_batch_len: config.batcher.batch_size_interval, max_proof_size: config.batcher.max_proof_size, @@ -321,6 +205,7 @@ impl Batcher { pre_verification_is_enabled: config.batcher.pre_verification_is_enabled, non_paying_config, posting_batch: Mutex::new(false), + batch_state: Mutex::new(batch_state), } } @@ -422,7 +307,7 @@ impl Batcher { async fn handle_message( self: Arc, message: Message, - ws_conn_sink: Arc, Message>>>, + ws_conn_sink: WsMessageSink, ) -> Result<(), Error> { // Deserialize verification data from message let client_msg: ClientMessage = match cbor_deserialize(message.into_data().as_slice()) { @@ -432,18 +317,17 @@ impl Batcher { return Ok(()); } }; + let msg_nonce = client_msg.verification_data.nonce; + debug!("Received message with nonce: {msg_nonce:?}",); - info!( - "Received message with nonce: {}", - client_msg.verification_data.nonce - ); - - if client_msg.verification_data.chain_id != self.chain_id { - warn!( - "Received message with incorrect chain id: {}", //This check does not save against "Holesky" and "HoleskyStage", since both are chain_id 17000 - client_msg.verification_data.chain_id - ); + // * ---------------------------------------------------* + // * Perform validations over the message * + // * ---------------------------------------------------* + // This check does not save against "Holesky" and "HoleskyStage", since both are chain_id 17000 + let msg_chain_id = client_msg.verification_data.chain_id; + if msg_chain_id != self.chain_id { + warn!("Received message with incorrect chain id: {msg_chain_id}"); send_message( ws_conn_sink.clone(), ValidityResponseMessage::InvalidChainId, @@ -453,16 +337,15 @@ impl Batcher { return Ok(()); } - if client_msg.verification_data.payment_service_addr != self.payment_service.address() { - warn!( - "Received message with incorrect payment service address: {}", //This checks saves against "Holesky" and "HoleskyStage", since each one has a different payment service address - client_msg.verification_data.payment_service_addr - ); + // This checks saves against "Holesky" and "HoleskyStage", since each one has a different payment service address + let msg_payment_service_addr = client_msg.verification_data.payment_service_addr; + if msg_payment_service_addr != self.payment_service.address() { + warn!("Received message with incorrect payment service address: {msg_payment_service_addr}"); send_message( ws_conn_sink.clone(), ValidityResponseMessage::InvalidPaymentServiceAddress( - client_msg.verification_data.payment_service_addr, + msg_payment_service_addr, self.payment_service.address(), ), ) @@ -472,208 +355,199 @@ impl Batcher { } info!("Verifying message signature..."); - if let Ok(addr) = client_msg.verify_signature() { - info!("Message signature verified"); - if self.is_nonpaying(&addr) { - self.handle_nonpaying_msg(ws_conn_sink.clone(), client_msg) - .await - } else { - info!("Handling paying message"); - if !self - .check_user_balance_and_increment_proof_count(&addr) - .await - { - send_message( - ws_conn_sink.clone(), - ValidityResponseMessage::InsufficientBalance(addr), - ) - .await; + let Ok(addr) = client_msg.verify_signature() else { + error!("Signature verification error"); + send_message( + ws_conn_sink.clone(), + ValidityResponseMessage::InvalidSignature, + ) + .await; + return Ok(()); + }; + info!("Message signature verified"); - return Ok(()); - } + let proof_size = client_msg.verification_data.verification_data.proof.len(); + if proof_size > self.max_proof_size { + error!("Proof size exceeds the maximum allowed size."); + send_message(ws_conn_sink.clone(), ValidityResponseMessage::ProofTooLarge).await; + return Ok(()); + } - let nonced_verification_data = client_msg.verification_data; - if nonced_verification_data.verification_data.proof.len() > self.max_proof_size { - error!("Proof size exceeds the maximum allowed size."); - send_message(ws_conn_sink.clone(), ValidityResponseMessage::ProofTooLarge) - .await; - return Ok(()); - } + let nonced_verification_data = client_msg.verification_data.clone(); - // When pre-verification is enabled, batcher will verify proofs for faster feedback with clients - if self.pre_verification_is_enabled - && !zk_utils::verify(&nonced_verification_data.verification_data).await - { - error!("Invalid proof detected. Verification failed."); - send_message(ws_conn_sink.clone(), ValidityResponseMessage::InvalidProof).await; - return Ok(()); // Send error message to the client and return - } + // When pre-verification is enabled, batcher will verify proofs for faster feedback with clients + if self.pre_verification_is_enabled + && !zk_utils::verify(&nonced_verification_data.verification_data).await + { + error!("Invalid proof detected. Verification failed."); + send_message(ws_conn_sink.clone(), ValidityResponseMessage::InvalidProof).await; + return Ok(()); + } - // Nonce and max fee verification - let nonce = nonced_verification_data.nonce; - let max_fee = nonced_verification_data.max_fee; + if self.is_nonpaying(&addr) { + return self + .handle_nonpaying_msg(ws_conn_sink.clone(), &client_msg) + .await; + } - if max_fee < U256::from(MIN_FEE_PER_PROOF) { - error!("The max fee signed in the message is less than the accepted minimum fee to be included in the batch."); - send_message(ws_conn_sink.clone(), ValidityResponseMessage::InvalidMaxFee) - .await; + info!("Handling paying message"); + + // We don't need a batch state lock here, since if the user locks its funds + // after the check, some blocks should pass until he can withdraw. + // It is safe to do just do this here. + if self.user_balance_is_unlocked(&addr).await { + send_message( + ws_conn_sink.clone(), + ValidityResponseMessage::InsufficientBalance(addr), + ) + .await; + return Ok(()); + } + + // Nonce and max fee verification + let max_fee = nonced_verification_data.max_fee; + if max_fee < U256::from(MIN_FEE_PER_PROOF) { + error!("The max fee signed in the message is less than the accepted minimum fee to be included in the batch."); + send_message(ws_conn_sink.clone(), ValidityResponseMessage::InvalidMaxFee).await; + return Ok(()); + } + + // Check that we had a user state entry for this user and insert it if not. + + // We aquire the lock first only to query if the user is already present and the lock is dropped. + // If it was not present, then the user nonce is queried to the Aligned contract. + // Lastly, we get a lock of the batch state again and insert the user state if it was still missing. + + let is_user_in_state: bool; + { + let batch_state_lock = self.batch_state.lock().await; + is_user_in_state = batch_state_lock.user_states.contains_key(&addr); + } + + if !is_user_in_state { + let ethereum_user_nonce = match self.get_user_nonce_from_ethereum(addr).await { + Ok(ethereum_user_nonce) => ethereum_user_nonce, + Err(e) => { + error!( + "Failed to get user nonce from Ethereum for address {addr:?}. Error: {e:?}" + ); + send_message(ws_conn_sink.clone(), ValidityResponseMessage::InvalidNonce).await; return Ok(()); } + }; + let user_state = UserState::new(ethereum_user_nonce); + let mut batch_state_lock = self.batch_state.lock().await; + batch_state_lock + .user_states + .entry(addr) + .or_insert(user_state); + } - let mut batch_state = self.batch_state.lock().await; - - let expected_user_nonce = match batch_state.user_nonces.get(&addr) { - Some(nonce) => *nonce, - None => { - let user_nonce = match self.get_user_nonce(addr).await { - Ok(nonce) => nonce, - Err(e) => { - error!("Failed to get user nonce for address {:?}: {:?}", addr, e); - send_message( - ws_conn_sink.clone(), - ValidityResponseMessage::InvalidNonce, - ) - .await; - - return Ok(()); - } - }; - - batch_state.user_nonces.insert(addr, user_nonce); - user_nonce - } - }; + // * ---------------------------------------------------* + // * Perform validations over user state * + // * ---------------------------------------------------* - let min_fee = match batch_state.user_min_fee.get(&addr) { - Some(fee) => *fee, - None => U256::max_value(), - }; + let Some(user_balance) = self.get_user_balance(&addr).await else { + error!("Could not get balance for address {addr:?}"); + send_message(ws_conn_sink.clone(), ValidityResponseMessage::EthRpcError).await; + return Ok(()); + }; - match expected_user_nonce.cmp(&nonce) { - std::cmp::Ordering::Less => { - // invalid, expected user nonce < nonce - warn!( - "Invalid nonce for address {addr}, had nonce {:?} < {:?}", - expected_user_nonce, nonce - ); - send_message(ws_conn_sink.clone(), ValidityResponseMessage::InvalidNonce) - .await; - return Ok(()); - } - std::cmp::Ordering::Equal => { - // if we are here nonce == expected_user_nonce - if !self - .handle_expected_nonce_message( - batch_state, - min_fee, - nonced_verification_data, - ws_conn_sink.clone(), - client_msg.signature, - addr, - ) - .await - { - // message should not be added to batch - return Ok(()); - }; - } - std::cmp::Ordering::Greater => { - // might be replacement message - // if the message is already in the batch - // we can check if we need to increment the fee - // get the entry with the same sender and nonce - if !self - .handle_replacement_message( - batch_state, - nonced_verification_data, - ws_conn_sink.clone(), - client_msg.signature, - addr, - expected_user_nonce, - ) - .await - { - // message should not be added to batch - return Ok(()); - } - } - } + // For now on until the message is fully processed, the batch state is locked + // This is needed because we need to query the user state to make validations and + // finally add the proof to the batch queue. - info!("Verification data message handled"); + let batch_state_lock = self.batch_state.lock().await; + let Some(proofs_in_batch) = batch_state_lock.get_user_proof_count(&addr).await else { + error!("Failed to get user proof count: User not found in user states, but it should have been already inserted"); + std::mem::drop(batch_state_lock); + send_message(ws_conn_sink.clone(), ValidityResponseMessage::InvalidNonce).await; + return Ok(()); + }; - send_message(ws_conn_sink, ValidityResponseMessage::Valid).await; - Ok(()) - } - } else { - error!("Signature verification error"); + if !self.check_min_balance(proofs_in_batch + 1, user_balance) { + std::mem::drop(batch_state_lock); send_message( ws_conn_sink.clone(), - ValidityResponseMessage::InvalidSignature, + ValidityResponseMessage::InsufficientBalance(addr), ) .await; - Ok(()) // Send error message to the client and return + return Ok(()); } - } - // Checks user has sufficient balance - // If user has sufficient balance, increments the user's proof count in the batch - async fn check_user_balance_and_increment_proof_count(&self, addr: &Address) -> bool { - if self.user_balance_is_unlocked(addr).await { - return false; - } - let mut batch_state = self.batch_state.lock().await; + let cached_user_nonce = batch_state_lock.get_user_nonce(&addr).await; + let Some(expected_nonce) = cached_user_nonce else { + error!("Failed to get cached user nonce: User not found in user states, but it should have been already inserted"); + std::mem::drop(batch_state_lock); + send_message(ws_conn_sink.clone(), ValidityResponseMessage::InvalidNonce).await; + return Ok(()); + }; - let user_proofs_in_batch = batch_state.get_user_proof_count(addr) + 1; + if expected_nonce < msg_nonce { + std::mem::drop(batch_state_lock); + warn!("Invalid nonce for address {addr}, had nonce {expected_nonce:?} < {msg_nonce:?}"); + send_message(ws_conn_sink.clone(), ValidityResponseMessage::InvalidNonce).await; + return Ok(()); + } - let user_balance = self.get_user_balance(addr).await; + // In this case, the message might be a replacement one. If it is valid, + // we replace the old entry with the new from the replacement message. + if expected_nonce > msg_nonce { + info!("Possible replacement message received: Expected nonce {expected_nonce:?} - message nonce: {msg_nonce:?}"); + self.handle_replacement_message( + batch_state_lock, + nonced_verification_data, + ws_conn_sink.clone(), + client_msg.signature, + addr, + ) + .await; - let min_balance = U256::from(user_proofs_in_batch) * U256::from(MIN_FEE_PER_PROOF); - if user_balance < min_balance { - return false; + return Ok(()); } - batch_state.increment_user_proof_count(addr); - true - } + let msg_max_fee = nonced_verification_data.max_fee; + let Some(user_min_fee) = batch_state_lock.get_user_min_fee(&addr).await else { + std::mem::drop(batch_state_lock); + send_message(ws_conn_sink.clone(), ValidityResponseMessage::InvalidNonce).await; + return Ok(()); + }; - /// Handles a message with an expected nonce. - /// If the max_fee is valid, it is added to the batch. - /// If the max_fee is invalid, a message is sent to the client. - /// Returns true if the message was added to the batch, false otherwise. - async fn handle_expected_nonce_message( - &self, - mut batch_state: tokio::sync::MutexGuard<'_, BatchState>, - min_fee: U256, - nonced_verification_data: NoncedVerificationData, - ws_conn_sink: Arc, Message>>>, - signature: Signature, - addr: Address, - ) -> bool { - let max_fee = nonced_verification_data.max_fee; - if max_fee > min_fee { - warn!( - "Invalid max fee for address {addr}, had fee {:?} < {:?}", - min_fee, max_fee - ); + if msg_max_fee > user_min_fee { + std::mem::drop(batch_state_lock); + warn!("Invalid max fee for address {addr}, had fee {user_min_fee:?} < {msg_max_fee:?}"); send_message(ws_conn_sink.clone(), ValidityResponseMessage::InvalidMaxFee).await; - return false; + return Ok(()); } - let nonce = nonced_verification_data.nonce; + // * ---------------------------------------------------------------------* + // * Add message data into the queue and update user state * + // * ---------------------------------------------------------------------* - batch_state.user_nonces.insert(addr, nonce + U256::one()); - batch_state.user_min_fee.insert(addr, max_fee); + if let Err(e) = self + .add_to_batch( + batch_state_lock, + nonced_verification_data, + ws_conn_sink.clone(), + client_msg.signature, + addr, + ) + .await + { + error!("Error while adding entry to batch: {e:?}"); + send_message(ws_conn_sink, ValidityResponseMessage::AddToBatchError).await; + return Ok(()); + }; - self.add_to_batch( - batch_state, - nonced_verification_data, - ws_conn_sink.clone(), - signature, - addr, - ) - .await; + info!("Verification data message handled"); + send_message(ws_conn_sink, ValidityResponseMessage::Valid).await; + Ok(()) + } - true + // Checks user has sufficient balance for paying all its the proofs in the current batch. + fn check_min_balance(&self, user_proofs_in_batch: usize, user_balance: U256) -> bool { + let min_balance = U256::from(user_proofs_in_batch) * U256::from(MIN_FEE_PER_PROOF); + user_balance >= min_balance } /// Handles a replacement message @@ -685,61 +559,50 @@ impl Batcher { /// Returns true if the message was replaced in the batch, false otherwise async fn handle_replacement_message( &self, - mut batch_state: tokio::sync::MutexGuard<'_, BatchState>, + mut batch_state_lock: MutexGuard<'_, BatchState>, nonced_verification_data: NoncedVerificationData, - ws_conn_sink: Arc, Message>>>, + ws_conn_sink: WsMessageSink, signature: Signature, addr: Address, - expected_user_nonce: U256, - ) -> bool { + ) { let replacement_max_fee = nonced_verification_data.max_fee; let nonce = nonced_verification_data.nonce; + let Some(entry) = batch_state_lock.get_entry(addr, nonce) else { + std::mem::drop(batch_state_lock); + warn!("Invalid nonce for address {addr}. Queue entry with nonce {nonce} not found"); + send_message(ws_conn_sink.clone(), ValidityResponseMessage::InvalidNonce).await; + return; + }; - let mut replacement_entry = match batch_state.get_entry(addr, nonce) { - Some(entry) => { - if entry.nonced_verification_data.max_fee < replacement_max_fee { - entry.clone() - } else { - warn!( - "Invalid replacement message for address {addr}, had fee {:?} < {:?}", - entry.nonced_verification_data.max_fee, replacement_max_fee - ); - send_message( - ws_conn_sink.clone(), - ValidityResponseMessage::InvalidReplacementMessage, - ) - .await; + let original_max_fee = entry.nonced_verification_data.max_fee; + if original_max_fee > replacement_max_fee { + std::mem::drop(batch_state_lock); + warn!("Invalid replacement message for address {addr}, had fee {original_max_fee:?} < {replacement_max_fee:?}"); + send_message( + ws_conn_sink.clone(), + ValidityResponseMessage::InvalidReplacementMessage, + ) + .await; - return false; - } - } - None => { - warn!( - "Invalid nonce for address {addr} Expected: {:?}, got: {:?}", - expected_user_nonce, nonce - ); - send_message(ws_conn_sink.clone(), ValidityResponseMessage::InvalidNonce).await; - return false; - } - }; + return; + } - info!( - "Replacing message for address {} with nonce {} and max fee {}", - addr, nonce, replacement_max_fee - ); + info!("Replacing message for address {addr} with nonce {nonce} and max fee {replacement_max_fee}"); + // The replacement entry is built from the old entry and validated for then to be replaced + let mut replacement_entry = entry.clone(); replacement_entry.signature = signature; replacement_entry.verification_data_commitment = nonced_verification_data.verification_data.clone().into(); replacement_entry.nonced_verification_data = nonced_verification_data; - // close old sink and replace with new one + // Close old sink in old entry and replace it with the new one { if let Some(messaging_sink) = replacement_entry.messaging_sink { let mut old_sink = messaging_sink.write().await; if let Err(e) = old_sink.close().await { // we dont want to exit here, just log the error - warn!("Error closing sink: {:?}", e); + warn!("Error closing sink: {e:?}"); } } else { warn!( @@ -749,16 +612,43 @@ impl Batcher { } replacement_entry.messaging_sink = Some(ws_conn_sink.clone()); - if let Some(msg) = batch_state.validate_and_increment_max_fee(replacement_entry) { - warn!("Invalid max fee"); - send_message(ws_conn_sink.clone(), msg).await; - return false; + if !batch_state_lock.replacement_entry_is_valid(&replacement_entry) { + std::mem::drop(batch_state_lock); + warn!("Invalid replacement message"); + send_message( + ws_conn_sink.clone(), + ValidityResponseMessage::InvalidReplacementMessage, + ) + .await; + return; } - true + info!( + "Replacement entry is valid, incrementing fee for sender: {:?}, nonce: {:?}, max_fee: {:?}", + replacement_entry.sender, replacement_entry.nonced_verification_data.nonce, replacement_max_fee + ); + + // remove the old entry and insert the new one + // note that the entries are considered equal for the priority queue + // if they have the same nonce and sender, so we can remove the old entry + // by calling remove with the new entry + batch_state_lock.batch_queue.remove(&replacement_entry); + batch_state_lock.batch_queue.push( + replacement_entry.clone(), + BatchQueueEntryPriority::new(replacement_max_fee, nonce), + ); + + let updated_min_fee_in_batch = batch_state_lock.get_user_min_fee_in_batch(&addr); + if batch_state_lock + .update_user_min_fee(&addr, updated_min_fee_in_batch) + .is_none() + { + std::mem::drop(batch_state_lock); + warn!("User state for address {addr:?} was not present in batcher user states, but it should be"); + }; } - async fn get_user_nonce( + async fn get_user_nonce_from_ethereum( &self, addr: Address, ) -> Result> { @@ -771,43 +661,86 @@ impl Batcher { /// Adds verification data to the current batch queue. async fn add_to_batch( &self, - mut batch_state: tokio::sync::MutexGuard<'_, BatchState>, + mut batch_state_lock: MutexGuard<'_, BatchState>, verification_data: NoncedVerificationData, - ws_conn_sink: Arc, Message>>>, + ws_conn_sink: WsMessageSink, proof_submitter_sig: Signature, - proof_submiter_addr: Address, - ) { + proof_submitter_addr: Address, + ) -> Result<(), BatcherError> { info!("Calculating verification data commitments..."); let verification_data_comm = verification_data.clone().into(); info!("Adding verification data to batch..."); let max_fee = verification_data.max_fee; let nonce = verification_data.nonce; - - batch_state.batch_queue.push( + batch_state_lock.batch_queue.push( BatchQueueEntry::new( verification_data, verification_data_comm, ws_conn_sink, proof_submitter_sig, - proof_submiter_addr, + proof_submitter_addr, ), BatchQueueEntryPriority::new(max_fee, nonce), ); + info!( "Current batch queue length: {}", - batch_state.batch_queue.len() + batch_state_lock.batch_queue.len() ); + + let mut proof_submitter_addr = proof_submitter_addr; + + // If the proof submitter is the nonpaying one, we should update the state + // of the replacement address. + proof_submitter_addr = if self.is_nonpaying(&proof_submitter_addr) { + self.get_nonpaying_replacement_addr() + .unwrap_or(proof_submitter_addr) + } else { + proof_submitter_addr + }; + + let Some(user_proof_count) = batch_state_lock + .get_user_proof_count(&proof_submitter_addr) + .await + else { + error!("User state of address {proof_submitter_addr} was not found when trying to update user state. This user state should have been present"); + std::mem::drop(batch_state_lock); + return Err(BatcherError::AddressNotFoundInUserStates( + proof_submitter_addr, + )); + }; + + // User state is updated + if batch_state_lock + .update_user_state( + &proof_submitter_addr, + nonce + U256::one(), + max_fee, + user_proof_count + 1, + ) + .is_none() + { + error!("User state of address {proof_submitter_addr} was not found when trying to update user state. This user state should have been present"); + std::mem::drop(batch_state_lock); + return Err(BatcherError::AddressNotFoundInUserStates( + proof_submitter_addr, + )); + }; + + Ok(()) } /// Given a new block number listened from the blockchain, checks if the current batch is ready to be posted. /// There are essentially two conditions to be checked: - /// * Has the current batch reached the minimum size to be posted? - /// * Has the received block number surpassed the maximum interval with respect to the last posted batch block? + /// * Has the current batch reached the minimum size to be posted? + /// * Has the received block number surpassed the maximum interval with respect to the last posted batch block? + /// /// Then the batch will be made as big as possible given this two conditions: - /// * The serialized batch size needs to be smaller than the maximum batch size - /// * The batch submission fee is less than the lowest `max fee` included the batch, - /// * And the batch submission fee is more than the highest `max fee` not included the batch. + /// * The serialized batch size needs to be smaller than the maximum batch size + /// * The batch submission fee is less than the lowest `max fee` included the batch, + /// * And the batch submission fee is more than the highest `max fee` not included the batch. + /// /// An extra sanity check is made to check if the batch size is 0, since it does not make sense to post /// an empty batch, even if the block interval has been reached. /// Once the batch meets the conditions for submission, the finalized batch is then passed to the @@ -817,9 +750,8 @@ impl Batcher { block_number: u64, gas_price: U256, ) -> Option> { - let mut batch_state = self.batch_state.lock().await; - let current_batch_len = batch_state.batch_queue.len(); - + let mut batch_state_lock = self.batch_state.lock().await; + let current_batch_len = batch_state_lock.batch_queue.len(); let last_uploaded_batch_block_lock = self.last_uploaded_batch_block.lock().await; // FIXME(marian): This condition should be changed to current_batch_size == 0 @@ -850,29 +782,44 @@ impl Batcher { // Set the batch posting flag to true *batch_posting = true; - - let batch_queue_copy = batch_state.batch_queue.clone(); - match batch_queue::try_build_batch(batch_queue_copy, gas_price, self.max_batch_size) { - Ok((resulting_batch_queue, finalized_batch)) => { - // Set the batch queue to batch queue copy - batch_state.batch_queue = resulting_batch_queue; - batch_state.update_user_proofs_in_batch_and_min_fee(); - Some(finalized_batch) - } - Err(BatcherError::BatchCostTooHigh) => { - // We cant post a batch since users are not willing to pay the needed fee, wait for more proofs - info!("No working batch found. Waiting for more proofs..."); - *batch_posting = false; - None - } - // FIXME: We should refactor this code and instead of returning None, return an error. - // See issue https://github.com/yetanotherco/aligned_layer/issues/1046. - Err(e) => { - error!("Unexpected error: {:?}", e); - *batch_posting = false; - None - } + let batch_queue_copy = batch_state_lock.batch_queue.clone(); + let (resulting_batch_queue, finalized_batch) = + batch_queue::try_build_batch(batch_queue_copy, gas_price, self.max_batch_size) + .inspect_err(|e| { + *batch_posting = false; + match e { + // We can't post a batch since users are not willing to pay the needed fee, wait for more proofs + BatcherError::BatchCostTooHigh => { + info!("No working batch found. Waiting for more proofs") + } + // FIXME: We should refactor this code and instead of returning None, return an error. + // See issue https://github.com/yetanotherco/aligned_layer/issues/1046. + e => error!("Unexpected error: {:?}", e), + } + }) + .ok()?; + + batch_state_lock.batch_queue = resulting_batch_queue; + let updated_user_proof_count_and_min_fee = + batch_state_lock.get_user_proofs_in_batch_and_min_fee(); + + let user_addresses: Vec
= batch_state_lock.user_states.keys().cloned().collect(); + for addr in user_addresses.iter() { + let (proof_count, min_fee) = updated_user_proof_count_and_min_fee + .get(addr) + .unwrap_or(&(0, U256::MAX)); + + // FIXME: The case where a the update functions return `None` can only happen when the user was not found + // in the `user_states` map should not really happen here, but doing this check so that we don't unwrap. + // Once https://github.com/yetanotherco/aligned_layer/issues/1046 is done we could return a more + // informative error. + + // Now we update the user states related to the batch (proof count in batch and min fee in batch) + batch_state_lock.update_user_proof_count(addr, *proof_count)?; + batch_state_lock.update_user_min_fee(addr, *min_fee)?; } + + Some(finalized_batch) } /// Takes the finalized batch as input and builds the merkle tree, posts verification data batch @@ -951,14 +898,13 @@ impl Batcher { return Err(e); }; - send_batch_inclusion_data_responses(finalized_batch, &batch_merkle_tree).await + connection::send_batch_inclusion_data_responses(finalized_batch, &batch_merkle_tree).await } async fn flush_queue_and_clear_nonce_cache(&self) { warn!("Resetting state... Flushing queue and nonces"); - let mut batch_state = self.batch_state.lock().await; - - for (entry, _) in batch_state.batch_queue.iter() { + let mut batch_state_lock = self.batch_state.lock().await; + for (entry, _) in batch_state_lock.batch_queue.iter() { if let Some(ws_sink) = entry.messaging_sink.as_ref() { send_message(ws_sink.clone(), ResponseMessage::BatchReset).await; } else { @@ -966,10 +912,29 @@ impl Batcher { } } - batch_state.batch_queue.clear(); - batch_state.user_nonces.clear(); - batch_state.user_proof_count_in_batch.clear(); - batch_state.user_min_fee.clear(); + let Some(nonpaying_replacement_addr) = self.get_nonpaying_replacement_addr() else { + batch_state_lock.batch_queue.clear(); + batch_state_lock.user_states.clear(); + return; + }; + + // If there is a nonpaying address configured, then fetch the correct nonce from Ethereum + // so that it is already loaded + + let Ok(nonpaying_replacement_addr_nonce) = self + .get_user_nonce_from_ethereum(nonpaying_replacement_addr) + .await + else { + batch_state_lock.batch_queue.clear(); + batch_state_lock.user_states.clear(); + return; + }; + batch_state_lock.batch_queue.clear(); + batch_state_lock.user_states.clear(); + let nonpaying_user_state = UserState::new(nonpaying_replacement_addr_nonce); + batch_state_lock + .user_states + .insert(nonpaying_replacement_addr, nonpaying_user_state); } /// Receives new block numbers, checks if conditions are met for submission and @@ -983,7 +948,7 @@ impl Batcher { } }; - while let Some(finalized_batch) = self.is_batch_ready(block_number, gas_price).await { + if let Some(finalized_batch) = self.is_batch_ready(block_number, gas_price).await { let batch_finalization_result = self .finalize_batch(block_number, finalized_batch, gas_price) .await; @@ -1120,8 +1085,7 @@ impl Batcher { { Ok(receipt) => Ok(receipt), Err(BatcherSendError::TransactionReverted(err)) => { - // dont retry with fallback - // just return the error + // Since transaction was reverted, we don't want to retry with fallback. warn!("Transaction reverted {:?}", err); Err(BatcherError::TransactionSendError) @@ -1158,204 +1122,141 @@ impl Batcher { .is_some_and(|non_paying_config| non_paying_config.address == *addr) } - /// Only relevant for testing and for users to easily use Aligned + fn get_nonpaying_replacement_addr(&self) -> Option
{ + let non_paying_conf = self.non_paying_config.as_ref()?; + Some(non_paying_conf.replacement.address()) + } + + /// Only relevant for testing and for users to easily use Aligned in testnet. async fn handle_nonpaying_msg( - self: Arc, - ws_conn_sink: Arc, Message>>>, - client_msg: ClientMessage, + &self, + ws_sink: WsMessageSink, + client_msg: &ClientMessage, ) -> Result<(), Error> { - let non_paying_config = self.non_paying_config.as_ref().unwrap(); - let addr = non_paying_config.replacement.address(); + info!("Handling nonpaying message"); + let Some(non_paying_config) = self.non_paying_config.as_ref() else { + warn!("There isn't a non-paying configuration loaded. This message will be ignored"); + send_message(ws_sink.clone(), ValidityResponseMessage::InvalidNonce).await; + return Ok(()); + }; - let user_balance = self.get_user_balance(&addr).await; + let replacement_addr = non_paying_config.replacement.address(); + let Some(replacement_user_balance) = self.get_user_balance(&replacement_addr).await else { + error!("Could not get balance for non-paying address {replacement_addr:?}"); + send_message( + ws_sink.clone(), + ValidityResponseMessage::InsufficientBalance(replacement_addr), + ) + .await; + return Ok(()); + }; - if user_balance == U256::from(0) { - error!("Insufficient funds for address {:?}", addr); + if replacement_user_balance == U256::from(0) { + error!("Insufficient funds for non-paying address {replacement_addr:?}"); send_message( - ws_conn_sink.clone(), - ValidityResponseMessage::InsufficientBalance(addr), + ws_sink.clone(), + ValidityResponseMessage::InsufficientBalance(replacement_addr), ) .await; - return Ok(()); // Send error message to the client and return + return Ok(()); } - if client_msg.verification_data.verification_data.proof.len() <= self.max_proof_size { - // When pre-verification is enabled, batcher will verify proofs for faster feedback with clients - if self.pre_verification_is_enabled - && !zk_utils::verify(&client_msg.verification_data.verification_data).await - { - error!("Invalid proof detected. Verification failed."); - send_message(ws_conn_sink.clone(), ValidityResponseMessage::InvalidProof).await; - return Ok(()); // Send error message to the client and return - } - - let nonced_verification_data = { - let mut batch_state = self.batch_state.lock().await; - - let nonpaying_nonce = match batch_state.user_nonces.entry(addr) { - Entry::Occupied(o) => o.into_mut(), - Entry::Vacant(vacant) => { - let nonce = match self.payment_service.user_nonces(addr).call().await { - Ok(nonce) => nonce, - Err(e) => { - error!("Failed to get nonce for address {:?}: {:?}", addr, e); - send_message( - ws_conn_sink.clone(), - ValidityResponseMessage::InvalidNonce, - ) - .await; - - return Ok(()); - } - }; - - vacant.insert(nonce) - } - }; - - info!("non paying nonce: {:?}", nonpaying_nonce); + let batch_state_lock = self.batch_state.lock().await; + let Some(non_paying_nonce) = batch_state_lock.get_user_nonce(&replacement_addr).await + else { + std::mem::drop(batch_state_lock); + error!("Nonce for non-paying address {replacement_addr:?} not found in cache."); + send_message(ws_sink.clone(), ValidityResponseMessage::InvalidProof).await; + return Ok(()); + }; - let nonce_value = *nonpaying_nonce; + debug!("Non-paying nonce: {:?}", non_paying_nonce); - *nonpaying_nonce += U256::one(); + let nonced_verification_data = NoncedVerificationData::new( + client_msg.verification_data.verification_data.clone(), + non_paying_nonce, + DEFAULT_MAX_FEE_PER_PROOF.into(), // 13_000 gas per proof * 100 gwei gas price (upper bound) + self.chain_id, + self.payment_service.address(), + ); - NoncedVerificationData::new( - client_msg.verification_data.verification_data.clone(), - nonce_value, - DEFAULT_MAX_FEE_PER_PROOF.into(), // 13_000 gas per proof * 100 gwei gas price (upper bound) - self.chain_id, - self.payment_service.address(), - ) - }; + let client_msg = ClientMessage::new( + nonced_verification_data.clone(), + non_paying_config.replacement.clone(), + ) + .await; - let client_msg = ClientMessage::new( - nonced_verification_data.clone(), - non_paying_config.replacement.clone(), + let signature = client_msg.signature; + let nonpaying_addr = non_paying_config.address; + if let Err(e) = self + .add_to_batch( + batch_state_lock, + nonced_verification_data, + ws_sink.clone(), + signature, + nonpaying_addr, ) - .await; - - let batch_state = self.batch_state.lock().await; - self.clone() - .add_to_batch( - batch_state, - nonced_verification_data, - ws_conn_sink.clone(), - client_msg.signature, - non_paying_config.address, - ) - .await; - } else { - error!("Proof is too large"); - send_message(ws_conn_sink.clone(), ValidityResponseMessage::ProofTooLarge).await; - return Ok(()); // Send error message to the client and return + .await + { + info!("Error while adding nonpaying address entry to batch: {e:?}"); + send_message(ws_sink, ValidityResponseMessage::AddToBatchError).await; + return Ok(()); }; - info!("Verification data message handled"); - - send_message(ws_conn_sink, ValidityResponseMessage::Valid).await; + info!("Non-paying verification data message handled"); + send_message(ws_sink, ValidityResponseMessage::Valid).await; Ok(()) } - async fn get_user_balance(&self, addr: &Address) -> U256 { - match self.payment_service.user_balances(*addr).call().await { - Ok(val) => val, - Err(_) => match self - .payment_service_fallback - .user_balances(*addr) - .call() - .await - { - Ok(balance) => balance, - Err(_) => { - warn!("Failed to get balance for address {:?}", addr); - U256::zero() - } - }, - } - } - - async fn user_balance_is_unlocked(&self, addr: &Address) -> bool { - let unlock_block = match self.payment_service.user_unlock_block(*addr).call().await { - Ok(val) => val, - Err(_) => match self - .payment_service_fallback - .user_unlock_block(*addr) - .call() - .await - { - Ok(unlock_block) => unlock_block, - Err(_) => { - warn!("Failed to get unlock block for address {:?}", addr); - U256::zero() - } - }, + /// Gets the balance of user with address `addr` from Ethereum. + /// Returns `None` if the balance couldn't be returned + /// FIXME: This should return a `Result` instead. + async fn get_user_balance(&self, addr: &Address) -> Option { + if let Ok(balance) = self.payment_service.user_balances(*addr).call().await { + return Some(balance); }; - unlock_block != U256::zero() + self.payment_service_fallback + .user_balances(*addr) + .call() + .await + .inspect_err(|_| warn!("Failed to get balance for address {:?}", addr)) + .ok() } - async fn get_gas_price(&self) -> Option { - match self.eth_ws_provider.get_gas_price().await { - Ok(gas_price) => Some(gas_price), // this is the block's max priority gas price, not the base fee - Err(_) => match self.eth_ws_provider_fallback.get_gas_price().await { - Ok(gas_price) => Some(gas_price), - Err(_) => { - warn!("Failed to get gas price"); - None - } - }, + async fn user_balance_is_unlocked(&self, addr: &Address) -> bool { + if let Ok(unlock_block) = self.payment_service.user_unlock_block(*addr).call().await { + return unlock_block != U256::zero(); } - } -} - -async fn send_batch_inclusion_data_responses( - finalized_batch: Vec, - batch_merkle_tree: &MerkleTree, -) -> Result<(), BatcherError> { - for (vd_batch_idx, entry) in finalized_batch.iter().enumerate() { - let batch_inclusion_data = BatchInclusionData::new(vd_batch_idx, batch_merkle_tree); - let response = ResponseMessage::BatchInclusionData(batch_inclusion_data); - - let serialized_response = cbor_serialize(&response) - .map_err(|e| BatcherError::SerializationError(e.to_string()))?; - - let Some(ws_sink) = entry.messaging_sink.as_ref() else { - return Err(BatcherError::WsSinkEmpty); - }; - - let sending_result = ws_sink - .write() + if let Ok(unlock_block) = self + .payment_service_fallback + .user_unlock_block(*addr) + .call() .await - .send(Message::binary(serialized_response)) - .await; - - match sending_result { - Err(Error::AlreadyClosed) => (), - Err(e) => error!("Error while sending batch inclusion data response: {}", e), - Ok(_) => (), + { + return unlock_block != U256::zero(); } - - info!("Response sent"); + warn!("Could not get user locking state"); + false } - Ok(()) -} - -async fn send_message( - ws_conn_sink: Arc, Message>>>, - message: T, -) { - match cbor_serialize(&message) { - Ok(serialized_response) => { - if let Err(err) = ws_conn_sink - .write() - .await - .send(Message::binary(serialized_response)) - .await - { - error!("Error while sending message: {}", err) - } + /// Gets the current gas price from Ethereum. + /// Returns `None` if the gas price couldn't be returned + /// FIXME: This should return a `Result` instead. + async fn get_gas_price(&self) -> Option { + if let Ok(gas_price) = self + .eth_ws_provider + .get_gas_price() + .await + .inspect_err(|e| warn!("Failed to get gas price. Trying with fallback: {e:?}")) + { + return Some(gas_price); } - Err(e) => error!("Error while serializing message: {}", e), + + self.eth_ws_provider_fallback + .get_gas_price() + .await + .inspect_err(|e| warn!("Failed to get gas price: {e:?}")) + .ok() } } diff --git a/batcher/aligned-batcher/src/types/batch_queue.rs b/batcher/aligned-batcher/src/types/batch_queue.rs index 9427cc9db..c90219d23 100644 --- a/batcher/aligned-batcher/src/types/batch_queue.rs +++ b/batcher/aligned-batcher/src/types/batch_queue.rs @@ -1,22 +1,16 @@ +use aligned_sdk::{ + communication::serialization::cbor_serialize, + core::types::{NoncedVerificationData, VerificationDataCommitment}, +}; use ethers::types::{Address, Signature, U256}; -use futures_util::stream::SplitSink; use priority_queue::PriorityQueue; use std::{ hash::{Hash, Hasher}, ops::ControlFlow, - sync::Arc, -}; -use tokio::{net::TcpStream, sync::RwLock}; -use tokio_tungstenite::{tungstenite::Message, WebSocketStream}; - -use aligned_sdk::{ - communication::serialization::cbor_serialize, - core::types::{NoncedVerificationData, VerificationDataCommitment}, }; use super::errors::BatcherError; - -type WsMessageSink = Arc, Message>>>; +use crate::connection::WsMessageSink; #[derive(Clone)] pub(crate) struct BatchQueueEntry { diff --git a/batcher/aligned-batcher/src/types/batch_state.rs b/batcher/aligned-batcher/src/types/batch_state.rs new file mode 100644 index 000000000..3e09377ac --- /dev/null +++ b/batcher/aligned-batcher/src/types/batch_state.rs @@ -0,0 +1,158 @@ +use std::collections::{hash_map::Entry, HashMap}; + +use super::{ + batch_queue::{BatchQueue, BatchQueueEntry}, + user_state::UserState, +}; +use ethers::types::{Address, U256}; +use log::debug; + +pub(crate) struct BatchState { + pub(crate) batch_queue: BatchQueue, + pub(crate) user_states: HashMap, +} + +impl BatchState { + pub(crate) fn new() -> Self { + Self { + batch_queue: BatchQueue::new(), + user_states: HashMap::new(), + } + } + + pub(crate) fn new_with_user_states(user_states: HashMap) -> Self { + Self { + batch_queue: BatchQueue::new(), + user_states, + } + } + + pub(crate) fn get_entry(&self, sender: Address, nonce: U256) -> Option<&BatchQueueEntry> { + self.batch_queue + .iter() + .map(|(entry, _)| entry) + .find(|entry| entry.sender == sender && entry.nonced_verification_data.nonce == nonce) + } + + pub(crate) fn get_user_state(&self, addr: &Address) -> Option<&UserState> { + self.user_states.get(addr) + } + + pub(crate) async fn get_user_nonce(&self, addr: &Address) -> Option { + let user_state = self.get_user_state(addr)?; + Some(user_state.nonce) + } + + pub(crate) async fn get_user_min_fee(&self, addr: &Address) -> Option { + let user_state = self.get_user_state(addr)?; + Some(user_state.min_fee) + } + + pub(crate) fn update_user_nonce(&mut self, addr: &Address, new_nonce: U256) -> Option { + if let Entry::Occupied(mut user_state) = self.user_states.entry(*addr) { + user_state.get_mut().nonce = new_nonce; + return Some(new_nonce); + } + None + } + + pub(crate) async fn get_user_proof_count(&self, addr: &Address) -> Option { + let user_state = self.get_user_state(addr)?; + Some(user_state.proofs_in_batch) + } + + /// Checks if the entry is valid + /// An entry is valid if there is no entry with the same sender, lower nonce and a lower fee + pub(crate) fn replacement_entry_is_valid( + &mut self, + replacement_entry: &BatchQueueEntry, + ) -> bool { + let replacement_max_fee = replacement_entry.nonced_verification_data.max_fee; + let nonce = replacement_entry.nonced_verification_data.nonce; + let sender = replacement_entry.sender; + + debug!( + "Checking validity of entry with sender: {:?}, nonce: {:?}, max_fee: {:?}", + sender, nonce, replacement_max_fee + ); + + // it is a valid entry only if there is no entry with the same sender, lower nonce and a lower fee + !self.batch_queue.iter().any(|(entry, _)| { + entry.sender == sender + && entry.nonced_verification_data.nonce < nonce + && entry.nonced_verification_data.max_fee < replacement_max_fee + }) + } + + pub(crate) fn get_user_min_fee_in_batch(&self, addr: &Address) -> U256 { + self.batch_queue + .iter() + .filter(|(e, _)| &e.sender == addr) + .map(|(e, _)| e.nonced_verification_data.max_fee) + .min() + .unwrap_or(U256::max_value()) + } + + pub(crate) fn update_user_min_fee( + &mut self, + addr: &Address, + new_min_fee: U256, + ) -> Option { + if let Entry::Occupied(mut user_state) = self.user_states.entry(*addr) { + user_state.get_mut().min_fee = new_min_fee; + return Some(new_min_fee); + } + None + } + + pub(crate) fn update_user_proof_count( + &mut self, + addr: &Address, + new_proof_count: usize, + ) -> Option { + if let Entry::Occupied(mut user_state) = self.user_states.entry(*addr) { + user_state.get_mut().proofs_in_batch = new_proof_count; + return Some(new_proof_count); + } + None + } + + /// Updates the user with address `addr` with the provided values of `new_nonce`, `new_min_fee` and + /// `new_proof_count`. + /// If state is updated successfully, returns the updated values inside a `Some()` + /// If the address was not found in the user states, returns `None` + pub(crate) fn update_user_state( + &mut self, + addr: &Address, + new_nonce: U256, + new_min_fee: U256, + new_proof_count: usize, + ) -> Option<(U256, U256, usize)> { + let updated_nonce = self.update_user_nonce(addr, new_nonce); + let updated_min_fee = self.update_user_min_fee(addr, new_min_fee); + let updated_proof_count = self.update_user_proof_count(addr, new_proof_count); + + if updated_nonce.is_some() && updated_min_fee.is_some() && updated_proof_count.is_some() { + return Some((new_nonce, new_min_fee, new_proof_count)); + } + None + } + + pub(crate) fn get_user_proofs_in_batch_and_min_fee(&self) -> HashMap { + let mut updated_user_states = HashMap::new(); + for (entry, _) in self.batch_queue.iter() { + let addr = entry.sender; + let user_min_fee = entry.nonced_verification_data.max_fee; + + let (proof_count, min_fee) = + updated_user_states.entry(addr).or_insert((0, user_min_fee)); + + *proof_count += 1; + if entry.nonced_verification_data.max_fee < *min_fee { + *min_fee = entry.nonced_verification_data.max_fee; + } + } + + updated_user_states + } +} diff --git a/batcher/aligned-batcher/src/types/errors.rs b/batcher/aligned-batcher/src/types/errors.rs index 4cf9ecd2a..c62de3576 100644 --- a/batcher/aligned-batcher/src/types/errors.rs +++ b/batcher/aligned-batcher/src/types/errors.rs @@ -1,6 +1,6 @@ use std::fmt; -use ethers::types::SignatureError; +use ethers::types::{Address, SignatureError}; use tokio_tungstenite::tungstenite; pub enum BatcherError { @@ -18,6 +18,7 @@ pub enum BatcherError { GasPriceError, BatchCostTooHigh, WsSinkEmpty, + AddressNotFoundInUserStates(Address), } impl From for BatcherError { @@ -83,6 +84,12 @@ impl fmt::Debug for BatcherError { "Websocket sink was found empty. This should only happen in tests" ) } + BatcherError::AddressNotFoundInUserStates(addr) => { + write!( + f, + "User with address {addr:?} was not found in Batcher user states cache" + ) + } } } } diff --git a/batcher/aligned-batcher/src/types/mod.rs b/batcher/aligned-batcher/src/types/mod.rs index 438bf92f8..893882786 100644 --- a/batcher/aligned-batcher/src/types/mod.rs +++ b/batcher/aligned-batcher/src/types/mod.rs @@ -1,3 +1,4 @@ pub(crate) mod batch_queue; - +pub(crate) mod batch_state; pub mod errors; +pub(crate) mod user_state; diff --git a/batcher/aligned-batcher/src/types/user_state.rs b/batcher/aligned-batcher/src/types/user_state.rs new file mode 100644 index 000000000..a1627b25f --- /dev/null +++ b/batcher/aligned-batcher/src/types/user_state.rs @@ -0,0 +1,21 @@ +use ethers::types::U256; + +pub(crate) struct UserState { + pub nonce: U256, + /// The minimum fee of a pending proof for a user. + /// This should always be the fee of the biggest pending nonce by the user. + /// This is used to check if a user is submitting a proof with a higher nonce and higher fee, + /// which is invalid and should be rejected. + pub min_fee: U256, + pub proofs_in_batch: usize, +} + +impl UserState { + pub(crate) fn new(nonce: U256) -> Self { + UserState { + nonce, + min_fee: U256::max_value(), + proofs_in_batch: 0, + } + } +} diff --git a/batcher/aligned-sdk/Cargo.toml b/batcher/aligned-sdk/Cargo.toml index cd71f0916..004499ffa 100644 --- a/batcher/aligned-sdk/Cargo.toml +++ b/batcher/aligned-sdk/Cargo.toml @@ -4,16 +4,28 @@ version = "0.1.0" edition = "2021" [dependencies] -ethers = { tag = "v2.0.15-fix-reconnections", features = ["ws", "rustls", "eip712"], git = "https://github.com/yetanotherco/ethers-rs.git" } -log = { version = "0.4.21"} +ethers = { tag = "v2.0.15-fix-reconnections", features = [ + "ws", + "rustls", + "eip712", +], git = "https://github.com/yetanotherco/ethers-rs.git" } +log = { version = "0.4.21" } serde_json = "1.0.117" tokio-tungstenite = { version = "0.23.1", features = ["native-tls"] } futures-util = "0.3.30" -tokio = { version = "1.37.0", features = ["io-std", "time", "macros", "rt", "rt-multi-thread", "sync"] } +tokio = { version = "1.37.0", features = [ + "io-std", + "time", + "macros", + "rt", + "rt-multi-thread", + "sync", +] } lambdaworks-crypto = { version = "0.7.0", features = ["serde"] } serde = { version = "1.0.201", features = ["derive"] } -sha3 = { version = "0.10.8"} +sha3 = { version = "0.10.8" } url = "2.5.0" hex = "0.4.3" ciborium = "=0.2.2" serde_repr = "0.1.19" +dialoguer = "0.11.0" diff --git a/batcher/aligned-sdk/src/communication/messaging.rs b/batcher/aligned-sdk/src/communication/messaging.rs index 3d6437054..6c64ea961 100644 --- a/batcher/aligned-sdk/src/communication/messaging.rs +++ b/batcher/aligned-sdk/src/communication/messaging.rs @@ -114,6 +114,15 @@ pub async fn send_messages( error!("Invalid replacement message!"); return Err(SubmitError::InvalidReplacementMessage); } + ValidityResponseMessage::AddToBatchError => { + error!("Error while pushing the entry to queue"); + return Err(SubmitError::AddToBatchError); + } + ValidityResponseMessage::EthRpcError => { + return Err(SubmitError::EthereumProviderError( + "Batcher experienced Eth RPC connection error".to_string(), + )); + } ValidityResponseMessage::InvalidPaymentServiceAddress(received_addr, expected_addr) => { error!( "Invalid payment service address, received: {}, expected: {}", diff --git a/batcher/aligned-sdk/src/core/constants.rs b/batcher/aligned-sdk/src/core/constants.rs new file mode 100644 index 000000000..844e39fa7 --- /dev/null +++ b/batcher/aligned-sdk/src/core/constants.rs @@ -0,0 +1,23 @@ +/// Batcher /// +pub const AGGREGATOR_GAS_COST: u128 = 400_000; +pub const BATCHER_SUBMISSION_BASE_GAS_COST: u128 = 125_000; +pub const ADDITIONAL_SUBMISSION_GAS_COST_PER_PROOF: u128 = 13_000; +pub const CONSTANT_GAS_COST: u128 = ((AGGREGATOR_GAS_COST * DEFAULT_AGGREGATOR_FEE_MULTIPLIER) + / DEFAULT_AGGREGATOR_FEE_DIVIDER) + + BATCHER_SUBMISSION_BASE_GAS_COST; +pub const DEFAULT_MAX_FEE_PER_PROOF: u128 = + ADDITIONAL_SUBMISSION_GAS_COST_PER_PROOF * 100_000_000_000; // gas_price = 100 Gwei = 0.0000001 ether (high gas price) +pub const MIN_FEE_PER_PROOF: u128 = ADDITIONAL_SUBMISSION_GAS_COST_PER_PROOF * 100_000_000; // gas_price = 0.1 Gwei = 0.0000000001 ether (low gas price) +pub const RESPOND_TO_TASK_FEE_LIMIT_MULTIPLIER: u128 = 5; // to set the respondToTaskFeeLimit variable higher than fee_for_aggregator +pub const RESPOND_TO_TASK_FEE_LIMIT_DIVIDER: u128 = 2; +pub const DEFAULT_AGGREGATOR_FEE_MULTIPLIER: u128 = 3; // to set the feeForAggregator variable higher than what was calculated +pub const DEFAULT_AGGREGATOR_FEE_DIVIDER: u128 = 2; + +/// SDK /// +/// Number of proofs we a batch for estimation. +/// This is the number of proofs in a batch of size n, where we set n = 32. +/// i.e. the user pays for the entire batch and his proof is instantly submitted. +pub const MAX_FEE_BATCH_PROOF_NUMBER: usize = 32; +/// Estimated number of proofs for batch submission. +/// This corresponds to the number of proofs to compute for a default max_fee. +pub const MAX_FEE_DEFAULT_PROOF_NUMBER: usize = 10; diff --git a/batcher/aligned-sdk/src/core/errors.rs b/batcher/aligned-sdk/src/core/errors.rs index bac70ca58..56327c451 100644 --- a/batcher/aligned-sdk/src/core/errors.rs +++ b/batcher/aligned-sdk/src/core/errors.rs @@ -15,6 +15,7 @@ pub enum AlignedError { VerificationError(VerificationError), NonceError(NonceError), ChainIdError(ChainIdError), + MaxFeeEstimateError(MaxFeeEstimateError), } impl From for AlignedError { @@ -41,6 +42,12 @@ impl From for AlignedError { } } +impl From for AlignedError { + fn from(e: MaxFeeEstimateError) -> Self { + AlignedError::MaxFeeEstimateError(e) + } +} + impl fmt::Display for AlignedError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -48,6 +55,7 @@ impl fmt::Display for AlignedError { AlignedError::VerificationError(e) => write!(f, "Verification error: {}", e), AlignedError::NonceError(e) => write!(f, "Nonce error: {}", e), AlignedError::ChainIdError(e) => write!(f, "Chain ID error: {}", e), + AlignedError::MaxFeeEstimateError(e) => write!(f, "Max fee estimate error: {}", e), } } } @@ -82,6 +90,7 @@ pub enum SubmitError { InsufficientBalance, InvalidPaymentServiceAddress(H160, H160), BatchSubmissionFailed(String), + AddToBatchError, GenericError(String), } @@ -190,6 +199,7 @@ impl fmt::Display for SubmitError { ) } SubmitError::ProofQueueFlushed => write!(f, "Batch reset"), + SubmitError::AddToBatchError => write!(f, "Error while adding entry to batch"), } } } @@ -251,6 +261,25 @@ impl fmt::Display for ChainIdError { } } +#[derive(Debug)] +pub enum MaxFeeEstimateError { + EthereumProviderError(String), + EthereumGasPriceError(String), +} + +impl fmt::Display for MaxFeeEstimateError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + MaxFeeEstimateError::EthereumProviderError(e) => { + write!(f, "Ethereum provider error: {}", e) + } + MaxFeeEstimateError::EthereumGasPriceError(e) => { + write!(f, "Failed to retreive the current gas price: {}", e) + } + } + } +} + #[derive(Debug)] pub enum VerifySignatureError { RecoverTypedDataError(SignatureError), @@ -279,3 +308,16 @@ impl fmt::Display for VerifySignatureError { } } } + +#[derive(Debug)] +pub enum PaymentError { + SendError(String), + SubmitError(String), + PaymentFailed, +} + +#[derive(Debug)] +pub enum BalanceError { + EthereumProviderError(String), + EthereumCallError(String), +} diff --git a/batcher/aligned-sdk/src/core/types.rs b/batcher/aligned-sdk/src/core/types.rs index 39134e2c7..b392ae6b0 100644 --- a/batcher/aligned-sdk/src/core/types.rs +++ b/batcher/aligned-sdk/src/core/types.rs @@ -69,6 +69,14 @@ impl NoncedVerificationData { } } +// Defines an estimate price preference for the user. +#[derive(Debug, Serialize, Deserialize, Clone)] +pub enum PriceEstimate { + Min, + Default, + Instant, +} + #[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct VerificationDataCommitment { pub proof_commitment: [u8; 32], @@ -313,8 +321,10 @@ pub enum ValidityResponseMessage { InvalidProof, InvalidMaxFee, InvalidReplacementMessage, + AddToBatchError, ProofTooLarge, InsufficientBalance(Address), + EthRpcError, InvalidPaymentServiceAddress(Address, Address), } diff --git a/batcher/aligned-sdk/src/lib.rs b/batcher/aligned-sdk/src/lib.rs index 8b897b6b0..55749ab20 100644 --- a/batcher/aligned-sdk/src/lib.rs +++ b/batcher/aligned-sdk/src/lib.rs @@ -1,4 +1,5 @@ pub mod core { + pub mod constants; pub mod errors; pub mod types; } diff --git a/batcher/aligned-sdk/src/sdk.rs b/batcher/aligned-sdk/src/sdk.rs index 4184f4908..5691dd820 100644 --- a/batcher/aligned-sdk/src/sdk.rs +++ b/batcher/aligned-sdk/src/sdk.rs @@ -5,9 +5,13 @@ use crate::{ protocol::check_protocol_version, }, core::{ + constants::{ + ADDITIONAL_SUBMISSION_GAS_COST_PER_PROOF, CONSTANT_GAS_COST, + MAX_FEE_BATCH_PROOF_NUMBER, MAX_FEE_DEFAULT_PROOF_NUMBER, + }, errors, types::{ - AlignedVerificationData, Network, ProvingSystemId, VerificationData, + AlignedVerificationData, Network, PriceEstimate, ProvingSystemId, VerificationData, VerificationDataCommitment, }, }, @@ -18,9 +22,11 @@ use crate::{ }; use ethers::{ + core::types::TransactionRequest, + middleware::SignerMiddleware, prelude::k256::ecdsa::SigningKey, providers::{Http, Middleware, Provider}, - signers::Wallet, + signers::{LocalWallet, Wallet}, types::{Address, H160, U256}, }; use sha3::{Digest, Keccak256}; @@ -92,6 +98,107 @@ pub async fn submit_multiple_and_wait_verification( Ok(aligned_verification_data) } +/// Returns the estimated `max_fee` depending on the batch inclusion preference of the user, based on the max priority gas price. +/// NOTE: The `max_fee` is computed from an rpc nodes max priority gas price. +/// To estimate the `max_fee` of a batch we use a compute the `max_fee` with respect to a batch of ~32 proofs present. +/// The `max_fee` estimates therefore are: +/// * `Min`: Specifies a `max_fee` equivalent to the cost of 1 proof in a 32 proof batch. +/// This estimates the lowest possible `max_fee` the user should specify for there proof with lowest priority. +/// * `Default`: Specifies a `max_fee` equivalent to the cost of 10 proofs in a 32 proof batch. +/// This estimates the `max_fee` the user should specify for inclusion within the batch. +/// * `Instant`: specifies a `max_fee` equivalent to the cost of all proofs within in a 32 proof batch. +/// This estimates the `max_fee` the user should specify to pay for the entire batch of proofs and have there proof included instantly. +/// # Arguments +/// * `eth_rpc_url` - The URL of the Ethereum RPC node. +/// * `estimate` - Enum specifying the type of price estimate: MIN, DEFAULT, INSTANT. +/// # Returns +/// The estimated `max_fee` in gas for a proof based on the users `PriceEstimate` as a `U256`. +/// # Errors +/// * `EthereumProviderError` if there is an error in the connection with the RPC provider. +/// * `EthereumGasPriceError` if there is an error retrieving the Ethereum gas price. +pub async fn estimate_fee( + eth_rpc_url: &str, + estimate: PriceEstimate, +) -> Result { + // Price of 1 proof in 32 proof batch + let fee_per_proof = fee_per_proof(eth_rpc_url, MAX_FEE_BATCH_PROOF_NUMBER).await?; + + let proof_price = match estimate { + PriceEstimate::Min => fee_per_proof, + PriceEstimate::Default => U256::from(MAX_FEE_DEFAULT_PROOF_NUMBER) * fee_per_proof, + PriceEstimate::Instant => U256::from(MAX_FEE_BATCH_PROOF_NUMBER) * fee_per_proof, + }; + Ok(proof_price) +} + +/// Returns the computed `max_fee` for a proof based on the number of proofs in a batch (`num_proofs_per_batch`) and +/// number of proofs (`num_proofs`) in that batch the user would pay for i.e (`num_proofs` / `num_proofs_per_batch`). +/// NOTE: The `max_fee` is computed from an rpc nodes max priority gas price. +/// # Arguments +/// * `eth_rpc_url` - The URL of the users Ethereum RPC node. +/// * `num_proofs` - number of proofs in a batch the user would pay for. +/// * `num_proofs_per_batch` - number of proofs within a batch. +/// # Returns +/// * The calculated `max_fee` as a `U256`. +/// # Errors +/// * `EthereumProviderError` if there is an error in the connection with the RPC provider. +/// * `EthereumGasPriceError` if there is an error retrieving the Ethereum gas price. +pub async fn compute_max_fee( + eth_rpc_url: &str, + num_proofs: usize, + num_proofs_per_batch: usize, +) -> Result { + let fee_per_proof = fee_per_proof(eth_rpc_url, num_proofs_per_batch).await?; + Ok(fee_per_proof * num_proofs) +} + +/// Returns the `fee_per_proof` based on the current gas price for a batch compromised of `num_proofs_per_batch` +/// i.e. (1 / `num_proofs_per_batch`). +// NOTE: The `fee_per_proof` is computed from an rpc nodes max priority gas price. +/// # Arguments +/// * `eth_rpc_url` - The URL of the users Ethereum RPC node. +/// * `num_proofs_per_batch` - number of proofs within a batch. +/// # Returns +/// * The fee per proof of a batch as a `U256`. +/// # Errors +/// * `EthereumProviderError` if there is an error in the connection with the RPC provider. +/// * `EthereumGasPriceError` if there is an error retrieving the Ethereum gas price. +pub async fn fee_per_proof( + eth_rpc_url: &str, + num_proofs_per_batch: usize, +) -> Result { + let eth_rpc_provider = + Provider::::try_from(eth_rpc_url).map_err(|e: url::ParseError| { + errors::MaxFeeEstimateError::EthereumProviderError(e.to_string()) + })?; + let gas_price = fetch_gas_price(ð_rpc_provider).await?; + + // Cost for estimate `num_proofs_per_batch` proofs + let estimated_gas_per_proof = (CONSTANT_GAS_COST + + ADDITIONAL_SUBMISSION_GAS_COST_PER_PROOF * num_proofs_per_batch as u128) + / num_proofs_per_batch as u128; + + // Price of 1 proof in 32 proof batch + let fee_per_proof = U256::from(estimated_gas_per_proof) * gas_price; + + Ok(fee_per_proof) +} + +async fn fetch_gas_price( + eth_rpc_provider: &Provider, +) -> Result { + let gas_price = match eth_rpc_provider.get_gas_price().await { + Ok(price) => price, + Err(e) => { + return Err(errors::MaxFeeEstimateError::EthereumGasPriceError( + e.to_string(), + )) + } + }; + + Ok(gas_price) +} + /// Submits multiple proofs to the batcher to be verified in Aligned. /// # Arguments /// * `batcher_url` - The url of the batcher to which the proof will be submitted. @@ -476,3 +583,121 @@ pub async fn get_chain_id(eth_rpc_url: &str) -> Result, LocalWallet>, + network: Network, +) -> Result { + let payment_service_address = get_payment_service_address(network); + let from = signer.address(); + + let tx = TransactionRequest::new() + .from(from) + .to(payment_service_address) + .value(amount); + + match signer + .send_transaction(tx, None) + .await + .map_err(|e| errors::PaymentError::SendError(e.to_string()))? + .await + .map_err(|e| errors::PaymentError::SubmitError(e.to_string()))? + { + Some(receipt) => Ok(receipt), + None => Err(errors::PaymentError::PaymentFailed), + } +} + +/// Returns the balance of a user in the payment service. +/// # Arguments +/// * `user` - The address of the user. +/// * `eth_rpc_url` - The URL of the Ethereum RPC node. +/// * `network` - The network on which the balance will be checked. +/// # Returns +/// * The balance of the user in the payment service. +/// # Errors +/// * `EthereumProviderError` if there is an error in the connection with the RPC provider. +/// * `EthereumCallError` if there is an error in the Ethereum call. +pub async fn get_balance_in_aligned( + user: Address, + eth_rpc_url: &str, + network: Network, +) -> Result { + let eth_rpc_provider = Provider::::try_from(eth_rpc_url) + .map_err(|e| errors::BalanceError::EthereumProviderError(e.to_string()))?; + + let payment_service_address = get_payment_service_address(network); + + match batcher_payment_service(eth_rpc_provider, payment_service_address).await { + Ok(batcher_payment_service) => { + let call = batcher_payment_service.user_balances(user); + + let result = call + .call() + .await + .map_err(|e| errors::BalanceError::EthereumCallError(e.to_string()))?; + + Ok(result) + } + Err(e) => Err(errors::BalanceError::EthereumCallError(e.to_string())), + } +} + +#[cfg(test)] +mod test { + //Public constants for convenience + pub const HOLESKY_PUBLIC_RPC_URL: &str = "https://ethereum-holesky-rpc.publicnode.com"; + use super::*; + + #[tokio::test] + async fn computed_max_fee_for_larger_batch_is_smaller() { + let small_fee = compute_max_fee(HOLESKY_PUBLIC_RPC_URL, 2, 10) + .await + .unwrap(); + let large_fee = compute_max_fee(HOLESKY_PUBLIC_RPC_URL, 5, 10) + .await + .unwrap(); + + assert!(small_fee < large_fee); + } + + #[tokio::test] + async fn computed_max_fee_for_more_proofs_larger_than_for_less_proofs() { + let small_fee = compute_max_fee(HOLESKY_PUBLIC_RPC_URL, 5, 20) + .await + .unwrap(); + let large_fee = compute_max_fee(HOLESKY_PUBLIC_RPC_URL, 5, 10) + .await + .unwrap(); + + assert!(small_fee < large_fee); + } + + #[tokio::test] + async fn estimate_fee_are_larger_than_one_another() { + let min_fee = estimate_fee(HOLESKY_PUBLIC_RPC_URL, PriceEstimate::Min) + .await + .unwrap(); + let default_fee = estimate_fee(HOLESKY_PUBLIC_RPC_URL, PriceEstimate::Default) + .await + .unwrap(); + let instant_fee = estimate_fee(HOLESKY_PUBLIC_RPC_URL, PriceEstimate::Instant) + .await + .unwrap(); + + assert!(min_fee < default_fee); + assert!(default_fee < instant_fee); + } +} diff --git a/batcher/aligned/install_aligned.sh b/batcher/aligned/install_aligned.sh index c2043cbf3..c81598d6e 100755 --- a/batcher/aligned/install_aligned.sh +++ b/batcher/aligned/install_aligned.sh @@ -8,14 +8,12 @@ BASE_DIR=$HOME ALIGNED_DIR="${ALIGNED_DIR-"$BASE_DIR/.aligned"}" ALIGNED_BIN_DIR="$ALIGNED_DIR/bin" ALIGNED_BIN_PATH="$ALIGNED_BIN_DIR/aligned" -#CURRENT_TAG=$(curl -s -L \ -# -H "Accept: application/vnd.github+json" \ -# -H "X-GitHub-Api-Version: 2022-11-28" \ -# https://api.github.com/repos/yetanotherco/aligned_layer/releases/latest \ -# | grep '"tag_name":' | awk -F'"' '{print $4}') -CURRENT_TAG=v0.6.0 +CURRENT_TAG=$(curl -s -L \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/yetanotherco/aligned_layer/releases/latest \ + | grep '"tag_name":' | awk -F'"' '{print $4}') RELEASE_URL="https://github.com/yetanotherco/aligned_layer/releases/download/$CURRENT_TAG/" - ARCH=$(uname -m) if [ "$ARCH" == "x86_64" ]; then diff --git a/batcher/aligned/send_burst_tasks.sh b/batcher/aligned/send_burst_tasks.sh index 25160bf13..f46464aa6 100755 --- a/batcher/aligned/send_burst_tasks.sh +++ b/batcher/aligned/send_burst_tasks.sh @@ -28,6 +28,6 @@ while true do # Run in backaground to be able to run onece per second, and not wait for the previous one to finish . ./batcher/aligned/generate_proof_and_send.sh $counter $burst & - sleep 1 + sleep 3 counter=$((counter + 1)) done diff --git a/batcher/aligned/src/main.rs b/batcher/aligned/src/main.rs index e41d5f135..f2f62f1a6 100644 --- a/batcher/aligned/src/main.rs +++ b/batcher/aligned/src/main.rs @@ -14,7 +14,7 @@ use aligned_sdk::core::{ }; use aligned_sdk::sdk::get_chain_id; use aligned_sdk::sdk::get_next_nonce; -use aligned_sdk::sdk::get_payment_service_address; +use aligned_sdk::sdk::{deposit_to_aligned, get_balance_in_aligned}; use aligned_sdk::sdk::{get_vk_commitment, is_proof_verified, submit_multiple}; use clap::Parser; use clap::Subcommand; @@ -412,6 +412,10 @@ async fn main() -> Result<(), AlignedError> { let amount = deposit_to_batcher_args.amount.replace("ether", ""); + let amount_ether = parse_ether(&amount).map_err(|e| { + SubmitError::EthereumProviderError(format!("Error while parsing amount: {}", e)) + })?; + let eth_rpc_url = deposit_to_batcher_args.eth_rpc_url; let eth_rpc_provider = @@ -439,99 +443,41 @@ async fn main() -> Result<(), AlignedError> { let client = SignerMiddleware::new(eth_rpc_provider.clone(), wallet.clone()); - let balance = client - .get_balance(wallet.address(), None) + match deposit_to_aligned(amount_ether, client, deposit_to_batcher_args.network.into()) .await - .map_err(|e| { - SubmitError::EthereumProviderError(format!( - "Error while getting balance: {}", - e - )) - })?; - - let amount_ether = parse_ether(&amount).map_err(|e| { - SubmitError::EthereumProviderError(format!("Error while parsing amount: {}", e)) - })?; - - if amount_ether <= U256::from(0) { - error!("Amount should be greater than 0"); - return Ok(()); - } - - if balance < amount_ether { - error!("Insufficient funds to pay to the batcher. Please deposit some Ether in your wallet."); - return Ok(()); - } - - let batcher_addr = get_payment_service_address(deposit_to_batcher_args.network.into()); - - let tx = TransactionRequest::new() - .to(batcher_addr) - .value(amount_ether) - .from(wallet.address()); - - info!("Sending {} ether to the batcher", amount); - - let tx = client - .send_transaction(tx, None) - .await - .map_err(|e| { - SubmitError::EthereumProviderError(format!( - "Error while sending transaction: {}", - e - )) - })? - .await - .map_err(|e| { - SubmitError::EthereumProviderError(format!( - "Error while sending transaction: {}", - e - )) - })?; - - if let Some(tx) = tx { - info!( - "Payment sent to the batcher successfully. Tx: 0x{:x}", - tx.transaction_hash - ); - } else { - error!("Transaction failed"); + { + Ok(receipt) => { + info!( + "Payment sent to the batcher successfully. Tx: 0x{:x}", + receipt.transaction_hash + ); + } + Err(e) => { + error!("Transaction failed: {:?}", e); + } } } GetUserBalance(get_user_balance_args) => { - let eth_rpc_url = get_user_balance_args.eth_rpc_url; - - let eth_rpc_provider = Provider::::try_from(eth_rpc_url).map_err(|e| { - SubmitError::EthereumProviderError(format!( - "Error while connecting to Ethereum: {}", - e - )) - })?; - - let user_address = - Address::from_str(&get_user_balance_args.user_address).map_err(|e| { - SubmitError::HexDecodingError(format!( - "Error while parsing user address: {}", - e - )) - })?; - - let batcher_addr = get_payment_service_address(get_user_balance_args.network.into()); - - let balance = get_user_balance(eth_rpc_provider, batcher_addr, user_address) - .await - .map_err(|e| { - SubmitError::EthereumProviderError(format!( - "Error while getting user balance: {}", - e - )) - })?; - - info!( - "User {} has {} ether in the batcher", + let user_address = H160::from_str(&get_user_balance_args.user_address).unwrap(); + match get_balance_in_aligned( user_address, - format_ether(balance) - ); + &get_user_balance_args.eth_rpc_url, + get_user_balance_args.network.into(), + ) + .await + { + Ok(balance) => { + info!( + "User {} has {} ether in the batcher", + user_address, + format_ether(balance) + ); + } + Err(e) => { + error!("Error while getting user balance: {:?}", e); + return Ok(()); + } + } } } diff --git a/common/proving_systems.go b/common/proving_systems.go index 7d1950181..023aa3eae 100644 --- a/common/proving_systems.go +++ b/common/proving_systems.go @@ -4,6 +4,8 @@ import ( "encoding/json" "fmt" "log" + + "github.com/fxamacker/cbor/v2" ) type ProvingSystemId uint16 @@ -86,6 +88,28 @@ func (t *ProvingSystemId) UnmarshalBinary(data []byte) error { return err } +func (s *ProvingSystemId) UnmarshalCBOR(data []byte) error { + var statusStr string + if err := cbor.Unmarshal(data, &statusStr); err != nil { + return err + } + + switch statusStr { + case "GnarkPlonkBls12_381": + *s = GnarkPlonkBls12_381 + case "GnarkPlonkBn254": + *s = GnarkPlonkBn254 + case "Groth16Bn254": + *s = Groth16Bn254 + case "SP1": + *s = SP1 + case "Risc0": + *s = Risc0 + } + + return nil +} + func (t ProvingSystemId) MarshalBinary() ([]byte, error) { // needs to be defined but should never be called return nil, fmt.Errorf("not implemented") diff --git a/contracts/bindings/AlignedLayerServiceManager/binding.go b/contracts/bindings/AlignedLayerServiceManager/binding.go index 0fbd918b7..90aad8448 100644 --- a/contracts/bindings/AlignedLayerServiceManager/binding.go +++ b/contracts/bindings/AlignedLayerServiceManager/binding.go @@ -84,7 +84,7 @@ type ISignatureUtilsSignatureWithSaltAndExpiry struct { // ContractAlignedLayerServiceManagerMetaData contains all meta data concerning the ContractAlignedLayerServiceManager contract. var ContractAlignedLayerServiceManagerMetaData = &bind.MetaData{ ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"__avsDirectory\",\"type\":\"address\",\"internalType\":\"contractIAVSDirectory\"},{\"name\":\"__rewardsCoordinator\",\"type\":\"address\",\"internalType\":\"contractIRewardsCoordinator\"},{\"name\":\"__registryCoordinator\",\"type\":\"address\",\"internalType\":\"contractIRegistryCoordinator\"},{\"name\":\"__stakeRegistry\",\"type\":\"address\",\"internalType\":\"contractIStakeRegistry\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"alignedAggregator\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"avsDirectory\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"batchersBalances\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"batchesState\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"taskCreatedBlock\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"responded\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"respondToTaskFeeLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"blsApkRegistry\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIBLSApkRegistry\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"checkPublicInput\",\"inputs\":[{\"name\":\"publicInput\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"hash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"checkSignatures\",\"inputs\":[{\"name\":\"msgHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"referenceBlockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structIBLSSignatureChecker.NonSignerStakesAndSignature\",\"components\":[{\"name\":\"nonSignerQuorumBitmapIndices\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"},{\"name\":\"nonSignerPubkeys\",\"type\":\"tuple[]\",\"internalType\":\"structBN254.G1Point[]\",\"components\":[{\"name\":\"X\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"Y\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"quorumApks\",\"type\":\"tuple[]\",\"internalType\":\"structBN254.G1Point[]\",\"components\":[{\"name\":\"X\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"Y\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"apkG2\",\"type\":\"tuple\",\"internalType\":\"structBN254.G2Point\",\"components\":[{\"name\":\"X\",\"type\":\"uint256[2]\",\"internalType\":\"uint256[2]\"},{\"name\":\"Y\",\"type\":\"uint256[2]\",\"internalType\":\"uint256[2]\"}]},{\"name\":\"sigma\",\"type\":\"tuple\",\"internalType\":\"structBN254.G1Point\",\"components\":[{\"name\":\"X\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"Y\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"quorumApkIndices\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"},{\"name\":\"totalStakeIndices\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"},{\"name\":\"nonSignerStakeIndices\",\"type\":\"uint32[][]\",\"internalType\":\"uint32[][]\"}]}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIBLSSignatureChecker.QuorumStakeTotals\",\"components\":[{\"name\":\"signedStakeForQuorum\",\"type\":\"uint96[]\",\"internalType\":\"uint96[]\"},{\"name\":\"totalStakeForQuorum\",\"type\":\"uint96[]\",\"internalType\":\"uint96[]\"}]},{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createAVSRewardsSubmission\",\"inputs\":[{\"name\":\"rewardsSubmissions\",\"type\":\"tuple[]\",\"internalType\":\"structIRewardsCoordinator.RewardsSubmission[]\",\"components\":[{\"name\":\"strategiesAndMultipliers\",\"type\":\"tuple[]\",\"internalType\":\"structIRewardsCoordinator.StrategyAndMultiplier[]\",\"components\":[{\"name\":\"strategy\",\"type\":\"address\",\"internalType\":\"contractIStrategy\"},{\"name\":\"multiplier\",\"type\":\"uint96\",\"internalType\":\"uint96\"}]},{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"contractIERC20\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"startTimestamp\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"duration\",\"type\":\"uint32\",\"internalType\":\"uint32\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"createNewTask\",\"inputs\":[{\"name\":\"batchMerkleRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"batchDataPointer\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"respondToTaskFeeLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"delegation\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIDelegationManager\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"depositToBatcher\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"deregisterOperatorFromAVS\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getOperatorRestakedStrategies\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRestakeableStrategies\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_initialOwner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_rewardsInitiator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_alignedAggregator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initializeAggregator\",\"inputs\":[{\"name\":\"_alignedAggregator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"registerOperatorToAVS\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"operatorSignature\",\"type\":\"tuple\",\"internalType\":\"structISignatureUtils.SignatureWithSaltAndExpiry\",\"components\":[{\"name\":\"signature\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"salt\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"expiry\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"registryCoordinator\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIRegistryCoordinator\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"respondToTaskV2\",\"inputs\":[{\"name\":\"batchMerkleRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"senderAddress\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"nonSignerStakesAndSignature\",\"type\":\"tuple\",\"internalType\":\"structIBLSSignatureChecker.NonSignerStakesAndSignature\",\"components\":[{\"name\":\"nonSignerQuorumBitmapIndices\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"},{\"name\":\"nonSignerPubkeys\",\"type\":\"tuple[]\",\"internalType\":\"structBN254.G1Point[]\",\"components\":[{\"name\":\"X\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"Y\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"quorumApks\",\"type\":\"tuple[]\",\"internalType\":\"structBN254.G1Point[]\",\"components\":[{\"name\":\"X\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"Y\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"apkG2\",\"type\":\"tuple\",\"internalType\":\"structBN254.G2Point\",\"components\":[{\"name\":\"X\",\"type\":\"uint256[2]\",\"internalType\":\"uint256[2]\"},{\"name\":\"Y\",\"type\":\"uint256[2]\",\"internalType\":\"uint256[2]\"}]},{\"name\":\"sigma\",\"type\":\"tuple\",\"internalType\":\"structBN254.G1Point\",\"components\":[{\"name\":\"X\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"Y\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"quorumApkIndices\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"},{\"name\":\"totalStakeIndices\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"},{\"name\":\"nonSignerStakeIndices\",\"type\":\"uint32[][]\",\"internalType\":\"uint32[][]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"rewardsInitiator\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setAggregator\",\"inputs\":[{\"name\":\"_alignedAggregator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRewardsInitiator\",\"inputs\":[{\"name\":\"newRewardsInitiator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setStaleStakesForbidden\",\"inputs\":[{\"name\":\"value\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"stakeRegistry\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIStakeRegistry\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"staleStakesForbidden\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"trySignatureAndApkVerification\",\"inputs\":[{\"name\":\"msgHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"apk\",\"type\":\"tuple\",\"internalType\":\"structBN254.G1Point\",\"components\":[{\"name\":\"X\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"Y\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"apkG2\",\"type\":\"tuple\",\"internalType\":\"structBN254.G2Point\",\"components\":[{\"name\":\"X\",\"type\":\"uint256[2]\",\"internalType\":\"uint256[2]\"},{\"name\":\"Y\",\"type\":\"uint256[2]\",\"internalType\":\"uint256[2]\"}]},{\"name\":\"sigma\",\"type\":\"tuple\",\"internalType\":\"structBN254.G1Point\",\"components\":[{\"name\":\"X\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"Y\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"pairingSuccessful\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"siganatureIsValid\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"updateAVSMetadataURI\",\"inputs\":[{\"name\":\"_metadataURI\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"verifyBatchInclusion\",\"inputs\":[{\"name\":\"proofCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"pubInputCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"provingSystemAuxDataCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"proofGeneratorAddr\",\"type\":\"bytes20\",\"internalType\":\"bytes20\"},{\"name\":\"batchMerkleRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"merkleProof\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"verificationDataBatchIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"senderAddress\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"verifyBatchInclusion\",\"inputs\":[{\"name\":\"proofCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"pubInputCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"provingSystemAuxDataCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"proofGeneratorAddr\",\"type\":\"bytes20\",\"internalType\":\"bytes20\"},{\"name\":\"batchMerkleRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"merkleProof\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"verificationDataBatchIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"withdraw\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"BatchVerified\",\"inputs\":[{\"name\":\"batchMerkleRoot\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"senderAddress\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"BatcherBalanceUpdated\",\"inputs\":[{\"name\":\"batcher\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newBalance\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"NewBatchV2\",\"inputs\":[{\"name\":\"batchMerkleRoot\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"senderAddress\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"taskCreatedBlock\",\"type\":\"uint32\",\"indexed\":false,\"internalType\":\"uint32\"},{\"name\":\"batchDataPointer\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"NewBatchV3\",\"inputs\":[{\"name\":\"batchMerkleRoot\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"senderAddress\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"taskCreatedBlock\",\"type\":\"uint32\",\"indexed\":false,\"internalType\":\"uint32\"},{\"name\":\"batchDataPointer\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"respondToTaskFeeLimit\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"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\":\"RewardsInitiatorUpdated\",\"inputs\":[{\"name\":\"prevRewardsInitiator\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"newRewardsInitiator\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"StaleStakesForbiddenUpdate\",\"inputs\":[{\"name\":\"value\",\"type\":\"bool\",\"indexed\":false,\"internalType\":\"bool\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"BatchAlreadyResponded\",\"inputs\":[{\"name\":\"batchIdentifierHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"BatchAlreadySubmitted\",\"inputs\":[{\"name\":\"batchIdentifierHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"BatchDoesNotExist\",\"inputs\":[{\"name\":\"batchIdentifierHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ExceededMaxRespondFee\",\"inputs\":[{\"name\":\"respondToTaskFeeLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"txCost\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InsufficientFunds\",\"inputs\":[{\"name\":\"batcher\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"required\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"available\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidDepositAmount\",\"inputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidQuorumThreshold\",\"inputs\":[{\"name\":\"signedStake\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"requiredStake\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"SenderIsNotAggregator\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"alignedAggregator\",\"type\":\"address\",\"internalType\":\"address\"}]}]", - Bin: "0x61018060405234801561001157600080fd5b5060405161562d38038061562d833981016040819052610030916102cf565b6001600160a01b0380851660805280841660a05280831660c052811660e052818484828461005c6101f7565b50505050806001600160a01b0316610100816001600160a01b031681525050806001600160a01b031663683048356040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100dd919061032e565b6001600160a01b0316610120816001600160a01b031681525050806001600160a01b0316635df459466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610135573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610159919061032e565b6001600160a01b0316610140816001600160a01b031681525050610120516001600160a01b031663df5cf7236040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d8919061032e565b6001600160a01b031661016052506101ee6101f7565b50505050610352565b600054610100900460ff16156102635760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811610156102b5576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b03811681146102cc57600080fd5b50565b600080600080608085870312156102e557600080fd5b84516102f0816102b7565b6020860151909450610301816102b7565b6040860151909350610312816102b7565b6060860151909250610323816102b7565b939692955090935050565b60006020828403121561034057600080fd5b815161034b816102b7565b9392505050565b60805160a05160c05160e051610100516101205161014051610160516151ce61045f6000396000818161065401526117dd01526000818161039701526119f00152600081816103cb01528181611bdd0152611dcd0152600081816104320152818161100f015281816114a30152818161164a0152611891015260008181610d4401528181610e9501528181610f2c01528181612a7001528181612be90152612c88015260008181610b6b01528181610bfa01528181610c7a0152818161216601528181612232015281816129ab0152612b4401526000818161303f015281816130fb01526131de0152600081816103fc015281816121ba0152818161228e015261230d01526151ce6000f3fe6080604052600436106101fd5760003560e01c806395c6d6041161010d578063d66eaabd116100a0578063f474b5201161006f578063f474b520146106ab578063f9120af6146106d8578063fa534dc0146106f8578063fc299dee14610718578063fce36c7d1461073857600080fd5b8063d66eaabd1461062f578063df5cf72314610642578063e481af9d14610676578063f2fde38b1461068b57600080fd5b8063ab21739a116100dc578063ab21739a1461056b578063b099627e1461058b578063b98d0908146105f5578063c0c53b8b1461060f57600080fd5b806395c6d604146104eb5780639926ee7d1461050b578063a364f4da1461052b578063a98fb3551461054b57600080fd5b80634ae07c37116101905780636d14a9871161015f5780636d14a9871461042057806370a0823114610454578063715018a614610498578063800fb61f146104ad5780638da5cb5b146104cd57600080fd5b80634ae07c37146103575780635df459461461038557806368304835146103b95780636b3aa72e146103ed57600080fd5b80633bc28c8c116101cc5780633bc28c8c146102cc578063416c7e5e146102ec5780634223d5511461030c5780634a5bf6321461031f57600080fd5b806306045a9114610213578063171f1d5b146102485780632e1a7d4d1461027f57806333cfb7b71461029f57600080fd5b3661020e5761020c3334610758565b005b600080fd5b34801561021f57600080fd5b5061023361022e36600461415d565b6107ed565b60405190151581526020015b60405180910390f35b34801561025457600080fd5b506102686102633660046142b0565b6108e4565b60408051921515835290151560208301520161023f565b34801561028b57600080fd5b5061020c61029a366004614301565b610a6e565b3480156102ab57600080fd5b506102bf6102ba36600461431a565b610b46565b60405161023f9190614337565b3480156102d857600080fd5b5061020c6102e736600461431a565b610ff9565b3480156102f857600080fd5b5061020c610307366004614386565b61100d565b61020c61031a36600461431a565b611144565b34801561032b57600080fd5b5060cb5461033f906001600160a01b031681565b6040516001600160a01b03909116815260200161023f565b34801561036357600080fd5b5061037761037236600461467e565b61114e565b60405161023f929190614719565b34801561039157600080fd5b5061033f7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103c557600080fd5b5061033f7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103f957600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061033f565b34801561042c57600080fd5b5061033f7f000000000000000000000000000000000000000000000000000000000000000081565b34801561046057600080fd5b5061048a61046f36600461431a565b6001600160a01b0316600090815260ca602052604090205490565b60405190815260200161023f565b3480156104a457600080fd5b5061020c612082565b3480156104b957600080fd5b5061020c6104c836600461431a565b612096565b3480156104d957600080fd5b506033546001600160a01b031661033f565b3480156104f757600080fd5b506102336105063660046147aa565b612136565b34801561051757600080fd5b5061020c6105263660046147f5565b61215b565b34801561053757600080fd5b5061020c61054636600461431a565b612227565b34801561055757600080fd5b5061020c6105663660046148ac565b6122ee565b34801561057757600080fd5b5061020c6105863660046148fc565b612342565b34801561059757600080fd5b506105d36105a6366004614301565b60c9602052600090815260409020805460019091015463ffffffff821691640100000000900460ff169083565b6040805163ffffffff909416845291151560208401529082015260600161023f565b34801561060157600080fd5b506097546102339060ff1681565b34801561061b57600080fd5b5061020c61062a366004614923565b612701565b61020c61063d36600461496e565b6127eb565b34801561064e57600080fd5b5061033f7f000000000000000000000000000000000000000000000000000000000000000081565b34801561068257600080fd5b506102bf6129a5565b34801561069757600080fd5b5061020c6106a636600461431a565b612d51565b3480156106b757600080fd5b5061048a6106c636600461431a565b60ca6020526000908152604090205481565b3480156106e457600080fd5b5061020c6106f336600461431a565b612dc7565b34801561070457600080fd5b506102336107133660046149c0565b612df1565b34801561072457600080fd5b5060655461033f906001600160a01b031681565b34801561074457600080fd5b5061020c610753366004614a40565b612e66565b8060000361078157604051632097692160e11b8152600481018290526024015b60405180910390fd5b6001600160a01b038216600090815260ca6020526040812080548392906107a9908490614acb565b90915550506001600160a01b038216600081815260ca6020908152604091829020549151918252600080516020615159833981519152910160405180910390a25050565b6000806001600160a01b038316610805575084610831565b8583604051602001610818929190614ade565b6040516020818303038152906040528051906020012090505b600081815260c9602052604081205463ffffffff1690036108565760009150506108d8565b600081815260c96020526040902054640100000000900460ff1661087e5760009150506108d8565b60408051602081018c90529081018a9052606081018990526001600160601b03198816608082015260009060940160408051601f19818403018152919052805160208201209091506108d287898389613215565b93505050505b98975050505050505050565b60008060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018787600001518860200151886000015160006002811061092c5761092c614af9565b60200201518951600160200201518a6020015160006002811061095157610951614af9565b60200201518b6020015160016002811061096d5761096d614af9565b602090810291909101518c518d8301516040516109ca9a99989796959401988952602089019790975260408801959095526060870193909352608086019190915260a085015260c084015260e08301526101008201526101200190565b6040516020818303038152906040528051906020012060001c6109ed9190614b0f565b9050610a60610a066109ff888461322d565b86906132be565b610a0e613353565b610a56610a4785610a41604080518082018252600080825260209182015281518083019092526001825260029082015290565b9061322d565b610a508c613413565b906132be565b886201d4c06134a2565b909890975095505050505050565b33600090815260ca6020526040902054811115610abf5733600081815260ca602052604090819020549051632e2a182f60e11b81526004810192909252602482018390526044820152606401610778565b33600090815260ca602052604081208054839290610ade908490614b31565b909155505033600081815260ca6020908152604091829020549151918252600080516020615159833981519152910160405180910390a2604051339082156108fc029083906000818181858888f19350505050158015610b42573d6000803e3d6000fd5b5050565b6040516309aa152760e11b81526001600160a01b0382811660048301526060916000917f000000000000000000000000000000000000000000000000000000000000000016906313542a4e90602401602060405180830381865afa158015610bb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd69190614b44565b60405163871ef04960e01b8152600481018290529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063871ef04990602401602060405180830381865afa158015610c41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c659190614b5d565b90506001600160c01b0381161580610cff57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639aa1653d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfa9190614b86565b60ff16155b15610d1f5760408051600080825260208201909252905b50949350505050565b6000610d33826001600160c01b03166136bc565b90506000805b8251811015610dff577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633ca5a5f5848381518110610d8357610d83614af9565b01602001516040516001600160e01b031960e084901b16815260f89190911c6004820152602401602060405180830381865afa158015610dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610deb9190614b44565b610df59083614acb565b9150600101610d39565b506000816001600160401b03811115610e1a57610e1a614035565b604051908082528060200260200182016040528015610e43578160200160208202803683370190505b5090506000805b8451811015610fec576000858281518110610e6757610e67614af9565b0160200151604051633ca5a5f560e01b815260f89190911c6004820181905291506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633ca5a5f590602401602060405180830381865afa158015610edc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f009190614b44565b905060005b81811015610fe1576040516356e4026d60e11b815260ff84166004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063adc804da906044016040805180830381865afa158015610f7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9e9190614bbe565b60000151868681518110610fb457610fb4614af9565b6001600160a01b039092166020928302919091019091015284610fd681614c01565b955050600101610f05565b505050600101610e4a565b5090979650505050505050565b61100161377e565b61100a816137d8565b50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561106b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108f9190614c1a565b6001600160a01b0316336001600160a01b03161461113b5760405162461bcd60e51b815260206004820152605c60248201527f424c535369676e6174757265436865636b65722e6f6e6c79436f6f7264696e6160448201527f746f724f776e65723a2063616c6c6572206973206e6f7420746865206f776e6560648201527f72206f6620746865207265676973747279436f6f7264696e61746f7200000000608482015260a401610778565b61100a81613841565b61100a8134610758565b604080518082019091526060808252602082015260008260400151516040518060400160405280600181526020016000815250511480156111aa57508260a0015151604051806040016040528060018152602001600081525051145b80156111d157508260c0015151604051806040016040528060018152602001600081525051145b80156111f857508260e0015151604051806040016040528060018152602001600081525051145b6112625760405162461bcd60e51b8152602060048201526041602482015260008051602061517983398151915260448201527f7265733a20696e7075742071756f72756d206c656e677468206d69736d6174636064820152600d60fb1b608482015260a401610778565b825151602084015151146112da5760405162461bcd60e51b815260206004820152604460248201819052600080516020615179833981519152908201527f7265733a20696e707574206e6f6e7369676e6572206c656e677468206d69736d6064820152630c2e8c6d60e31b608482015260a401610778565b4363ffffffff168463ffffffff16106113495760405162461bcd60e51b815260206004820152603c602482015260008051602061517983398151915260448201527f7265733a20696e76616c6964207265666572656e636520626c6f636b000000006064820152608401610778565b60408051808201825260008082526020808301829052835180850185526060808252818301528451808601865260018082529083019390935284518381528086019095529293919082810190803683370190505060208281019190915260408051808201825260018082526000919093015280518281528082019091529081602001602082028036833701905050815260408051808201909152606080825260208201528560200151516001600160401b0381111561140a5761140a614035565b604051908082528060200260200182016040528015611433578160200160208202803683370190505b5081526020860151516001600160401b0381111561145357611453614035565b60405190808252806020026020018201604052801561147c578160200160208202803683370190505b508160200181905250600061152860405180604001604052806001815260200160008152507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639aa1653d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115239190614b86565b613888565b905060005b8760200151518110156117b9576115728860200151828151811061155357611553614af9565b6020026020010151805160009081526020918201519091526040902090565b8360200151828151811061158857611588614af9565b602090810291909101015280156116485760208301516115a9600183614b31565b815181106115b9576115b9614af9565b602002602001015160001c836020015182815181106115da576115da614af9565b602002602001015160001c11611648576040805162461bcd60e51b815260206004820152602481019190915260008051602061517983398151915260448201527f7265733a206e6f6e5369676e65725075626b657973206e6f7420736f727465646064820152608401610778565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166304ec63518460200151838151811061168d5761168d614af9565b60200260200101518b8b6000015185815181106116ac576116ac614af9565b60200260200101516040518463ffffffff1660e01b81526004016116e99392919092835263ffffffff918216602084015216604082015260600190565b602060405180830381865afa158015611706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172a9190614b5d565b6001600160c01b03168360000151828151811061174957611749614af9565b6020026020010181815250506117af6109ff611783848660000151858151811061177557611775614af9565b60200260200101511661391b565b8a60200151848151811061179957611799614af9565b602002602001015161394690919063ffffffff16565b945060010161152d565b50506117c483613a29565b60975490935060ff166000816117db57600061185d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c448feb86040518163ffffffff1660e01b8152600401602060405180830381865afa158015611839573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185d9190614b44565b905060005b604051806040016040528060018152602001600081525051811015611f535782156119ee578963ffffffff16827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663249a0c42604051806040016040528060018152602001600081525085815181106118e6576118e6614af9565b01602001516040516001600160e01b031960e084901b16815260f89190911c6004820152602401602060405180830381865afa15801561192a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194e9190614b44565b6119589190614acb565b116119ee5760405162461bcd60e51b8152602060048201526066602482015260008051602061517983398151915260448201527f7265733a205374616b6552656769737472792075706461746573206d7573742060648201527f62652077697468696e207769746864726177616c44656c6179426c6f636b732060848201526577696e646f7760d01b60a482015260c401610778565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166368bccaac60405180604001604052806001815260200160008152508381518110611a4557611a45614af9565b602001015160f81c60f81b60f81c8c8c60a001518581518110611a6a57611a6a614af9565b60209081029190910101516040516001600160e01b031960e086901b16815260ff909316600484015263ffffffff9182166024840152166044820152606401602060405180830381865afa158015611ac6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aea9190614c37565b6001600160401b031916611b0d8a60400151838151811061155357611553614af9565b67ffffffffffffffff191614611ba95760405162461bcd60e51b8152602060048201526061602482015260008051602061517983398151915260448201527f7265733a2071756f72756d41706b206861736820696e2073746f72616765206460648201527f6f6573206e6f74206d617463682070726f76696465642071756f72756d2061706084820152606b60f81b60a482015260c401610778565b611bd989604001518281518110611bc257611bc2614af9565b6020026020010151876132be90919063ffffffff16565b95507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c8294c5660405180604001604052806001815260200160008152508381518110611c3257611c32614af9565b602001015160f81c60f81b60f81c8c8c60c001518581518110611c5757611c57614af9565b60209081029190910101516040516001600160e01b031960e086901b16815260ff909316600484015263ffffffff9182166024840152166044820152606401602060405180830381865afa158015611cb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd79190614c62565b85602001518281518110611ced57611ced614af9565b6001600160601b03909216602092830291909101820152850151805182908110611d1957611d19614af9565b602002602001015185600001518281518110611d3757611d37614af9565b60200260200101906001600160601b031690816001600160601b0316815250506000805b8a6020015151811015611f4957611dc686600001518281518110611d8157611d81614af9565b602002602001015160405180604001604052806001815260200160008152508581518110611db157611db1614af9565b016020015160f81c60ff161c60019081161490565b15611f41577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f2be94ae60405180604001604052806001815260200160008152508581518110611e2257611e22614af9565b602001015160f81c60f81b60f81c8e89602001518581518110611e4757611e47614af9565b60200260200101518f60e001518881518110611e6557611e65614af9565b60200260200101518781518110611e7e57611e7e614af9565b60209081029190910101516040516001600160e01b031960e087901b16815260ff909416600485015263ffffffff92831660248501526044840191909152166064820152608401602060405180830381865afa158015611ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f069190614c62565b8751805185908110611f1a57611f1a614af9565b60200260200101818151611f2e9190614c7f565b6001600160601b03169052506001909101905b600101611d5b565b5050600101611862565b505050600080611f6d8a868a606001518b608001516108e4565b9150915081611fde5760405162461bcd60e51b8152602060048201526043602482015260008051602061517983398151915260448201527f7265733a2070616972696e6720707265636f6d70696c652063616c6c206661696064820152621b195960ea1b608482015260a401610778565b8061203f5760405162461bcd60e51b8152602060048201526039602482015260008051602061517983398151915260448201527f7265733a207369676e617475726520697320696e76616c6964000000000000006064820152608401610778565b5050600087826020015160405160200161205a929190614c9e565b60408051808303601f1901815291905280516020909101209299929850919650505050505050565b61208a61377e565b6120946000613ac4565b565b600054600290610100900460ff161580156120b8575060005460ff8083169116105b6120d45760405162461bcd60e51b815260040161077890614ce6565b6000805461ffff191660ff8316176101001790556120f182612dc7565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6000818484604051612149929190614d34565b60405180910390201490509392505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146121a35760405162461bcd60e51b815260040161077890614d44565b604051639926ee7d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639926ee7d906121f19085908590600401614e02565b600060405180830381600087803b15801561220b57600080fd5b505af115801561221f573d6000803e3d6000fd5b505050505050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461226f5760405162461bcd60e51b815260040161077890614d44565b6040516351b27a6d60e11b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063a364f4da906024015b600060405180830381600087803b1580156122d357600080fd5b505af11580156122e7573d6000803e3d6000fd5b5050505050565b6122f661377e565b60405163a98fb35560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a98fb355906122b9908490600401614e4d565b60cb546001600160a01b031633146123825760cb54604051632cbe419560e01b81523360048201526001600160a01b039091166024820152604401610778565b60005a90506000848460405160200161239c929190614ade565b60408051601f198184030181529181528151602092830120600081815260c990935290822080549193509163ffffffff90911690036123f1576040516311cb69a760e11b815260048101839052602401610778565b8054640100000000900460ff161561241f57604051634e78d7f960e11b815260048101839052602401610778565b805464ff00000000191664010000000017815560018101546001600160a01b038616600090815260ca602052604090205410156124a25760018101546001600160a01b038616600081815260ca602052604090819020549051632e2a182f60e11b8152600481019290925260248201929092526044810191909152606401610778565b80546000906124b990849063ffffffff168761114e565b509050604360ff1681602001516000815181106124d8576124d8614af9565b60200260200101516124ea9190614e60565b6001600160601b03166064826000015160008151811061250c5761250c614af9565b60200260200101516001600160601b03166125279190614e89565b10156125ba576064816000015160008151811061254657612546614af9565b60200260200101516001600160601b03166125619190614e89565b604360ff16826020015160008151811061257d5761257d614af9565b602002602001015161258f9190614e60565b60405163530f5c4560e11b815260048101929092526001600160601b03166024820152604401610778565b6040516001600160a01b038716815287907f8511746b73275e06971968773119b9601fc501d7bdf3824d8754042d148940e29060200160405180910390a260003a5a6126069087614b31565b6126139062011170614acb565b61261d9190614e89565b9050826001015481111561265457600183015460405163437e283f60e11b8152600481019190915260248101829052604401610778565b6001600160a01b038716600090815260ca60205260408120805483929061267c908490614b31565b90915550506001600160a01b038716600081815260ca6020908152604091829020549151918252600080516020615159833981519152910160405180910390a260cb546040516001600160a01b039091169082156108fc029083906000818181858888f193505050501580156126f6573d6000803e3d6000fd5b505050505050505050565b600054610100900460ff16158080156127215750600054600160ff909116105b8061273b5750303b15801561273b575060005460ff166001145b6127575760405162461bcd60e51b815260040161077890614ce6565b6000805460ff19166001179055801561277a576000805461ff0019166101001790555b6127848484613b16565b60cb80546001600160a01b0319166001600160a01b03841617905580156127e5576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b60008433604051602001612800929190614ade565b60408051601f198184030181529181528151602092830120600081815260c990935291205490915063ffffffff161561284f57604051630c40bc4360e21b815260048101829052602401610778565b34156128ac5733600090815260ca602052604081208054349290612874908490614acb565b909155505033600081815260ca6020908152604091829020549151918252600080516020615159833981519152910160405180910390a25b33600090815260ca60205260409020548211156128fd5733600081815260ca602052604090819020549051632e2a182f60e11b81526004810192909252602482018490526044820152606401610778565b604080516060810182526000602080830182815263ffffffff43818116865285870189815288865260c99094529386902085518154935115156401000000000264ffffffffff1990941692169190911791909117815590516001909101559151909187917f8801fc966deb2c8f563a103c35c9e80740585c292cd97518587e6e7927e6af5591612995913391908a908a908a90614ea0565b60405180910390a2505050505050565b606060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639aa1653d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2b9190614b86565b60ff16905080600003612a4c57505060408051600081526020810190915290565b6000805b82811015612af757604051633ca5a5f560e01b815260ff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633ca5a5f590602401602060405180830381865afa158015612abf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae39190614b44565b612aed9083614acb565b9150600101612a50565b506000816001600160401b03811115612b1257612b12614035565b604051908082528060200260200182016040528015612b3b578160200160208202803683370190505b5090506000805b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639aa1653d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc49190614b86565b60ff16811015612d4757604051633ca5a5f560e01b815260ff821660048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633ca5a5f590602401602060405180830381865afa158015612c38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5c9190614b44565b905060005b81811015612d3d576040516356e4026d60e11b815260ff84166004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063adc804da906044016040805180830381865afa158015612cd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cfa9190614bbe565b60000151858581518110612d1057612d10614af9565b6001600160a01b039092166020928302919091019091015283612d3281614c01565b945050600101612c61565b5050600101612b42565b5090949350505050565b612d5961377e565b6001600160a01b038116612dbe5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610778565b61100a81613ac4565b612dcf61377e565b60cb80546001600160a01b0319166001600160a01b0392909216919091179055565b6040516306045a9160e01b815260009030906306045a9190612e25908b908b908b908b908b908b908b908b90600401614ef7565b602060405180830381865afa158015612e42573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d89190614f59565b6065546001600160a01b03163314612efb5760405162461bcd60e51b815260206004820152604c60248201527f536572766963654d616e61676572426173652e6f6e6c7952657761726473496e60448201527f69746961746f723a2063616c6c6572206973206e6f742074686520726577617260648201526b32399034b734ba34b0ba37b960a11b608482015260a401610778565b60005b818110156131c657828282818110612f1857612f18614af9565b9050602002810190612f2a9190614f76565b612f3b90604081019060200161431a565b6001600160a01b03166323b872dd3330868686818110612f5d57612f5d614af9565b9050602002810190612f6f9190614f76565b604080516001600160e01b031960e087901b1681526001600160a01b039485166004820152939092166024840152013560448201526064016020604051808303816000875af1158015612fc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fea9190614f59565b506000838383818110612fff57612fff614af9565b90506020028101906130119190614f76565b61302290604081019060200161431a565b604051636eb1769f60e11b81523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152919091169063dd62ed3e90604401602060405180830381865afa158015613090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130b49190614b44565b90508383838181106130c8576130c8614af9565b90506020028101906130da9190614f76565b6130eb90604081019060200161431a565b6001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000008387878781811061312d5761312d614af9565b905060200281019061313f9190614f76565b6040013561314d9190614acb565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015613198573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131bc9190614f59565b5050600101612efe565b5060405163fce36c7d60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063fce36c7d906121f19085908590600401614ffd565b600083613223868585613b93565b1495945050505050565b6040805180820190915260008082526020820152613249613f43565b835181526020808501519082015260408082018490526000908360608460076107d05a03fa9050808061327857fe5b50806132b65760405162461bcd60e51b815260206004820152600d60248201526c1958cb5b5d5b0b59985a5b1959609a1b6044820152606401610778565b505092915050565b60408051808201909152600080825260208201526132da613f61565b835181526020808501518183015283516040808401919091529084015160608301526000908360808460066107d05a03fa9050808061331557fe5b50806132b65760405162461bcd60e51b815260206004820152600d60248201526c1958cb5859190b59985a5b1959609a1b6044820152606401610778565b61335b613f7f565b50604080516080810182527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c28183019081527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6060830152815281518083019092527f275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec82527f1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d60208381019190915281019190915290565b60408051808201909152600080825260208201526000808061344360008051602061513983398151915286614b0f565b90505b61344f81613c90565b90935091506000805160206151398339815191528283098303613488576040805180820190915290815260208101919091529392505050565b600080516020615139833981519152600182089050613446565b6040805180820182528681526020808201869052825180840190935286835282018490526000918291906134d4613fa4565b60005b600281101561368f5760006134ed826006614e89565b905084826002811061350157613501614af9565b60200201515183613513836000614acb565b600c811061352357613523614af9565b602002015284826002811061353a5761353a614af9565b602002015160200151838260016135519190614acb565b600c811061356157613561614af9565b602002015283826002811061357857613578614af9565b602002015151518361358b836002614acb565b600c811061359b5761359b614af9565b60200201528382600281106135b2576135b2614af9565b60200201515160016020020151836135cb836003614acb565b600c81106135db576135db614af9565b60200201528382600281106135f2576135f2614af9565b60200201516020015160006002811061360d5761360d614af9565b60200201518361361e836004614acb565b600c811061362e5761362e614af9565b602002015283826002811061364557613645614af9565b60200201516020015160016002811061366057613660614af9565b602002015183613671836005614acb565b600c811061368157613681614af9565b6020020152506001016134d7565b50613698613fc3565b60006020826101808560088cfa9151919c9115159b50909950505050505050505050565b60606000806136ca8461391b565b61ffff166001600160401b038111156136e5576136e5614035565b6040519080825280601f01601f19166020018201604052801561370f576020820181803683370190505b5090506000805b825182108015613727575061010081105b15612d47576001811b93508584161561376e578060f81b83838151811061375057613750614af9565b60200101906001600160f81b031916908160001a9053508160010191505b61377781614c01565b9050613716565b6033546001600160a01b031633146120945760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610778565b606554604080516001600160a01b03928316815291831660208301527fe11cddf1816a43318ca175bbc52cd0185436e9cbead7c83acc54a73e461717e3910160405180910390a1606580546001600160a01b0319166001600160a01b0392909216919091179055565b6097805460ff19168215159081179091556040519081527f40e4ed880a29e0f6ddce307457fb75cddf4feef7d3ecb0301bfdf4976a0e2dfc9060200160405180910390a150565b60008061389484613d12565b9050808360ff166001901b116139125760405162461bcd60e51b815260206004820152603f60248201527f4269746d61705574696c732e6f72646572656442797465734172726179546f4260448201527f69746d61703a206269746d61702065786365656473206d61782076616c7565006064820152608401610778565b90505b92915050565b6000805b821561391557613930600184614b31565b909216918061393e81615117565b91505061391f565b60408051808201909152600080825260208201526102008261ffff16106139a25760405162461bcd60e51b815260206004820152601060248201526f7363616c61722d746f6f2d6c6172676560801b6044820152606401610778565b8161ffff166001036139b5575081613915565b6040805180820190915260008082526020820181905284906001905b8161ffff168661ffff1610613a1e57600161ffff871660ff83161c81169003613a01576139fe84846132be565b93505b613a0b83846132be565b92506201fffe600192831b1691016139d1565b509195945050505050565b60408051808201909152600080825260208201528151158015613a4e57506020820151155b15613a6c575050604080518082019091526000808252602082015290565b6040518060400160405280836000015181526020016000805160206151398339815191528460200151613a9f9190614b0f565b613ab790600080516020615139833981519152614b31565b905292915050565b919050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16613b815760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610778565b613b8a82613ac4565b610b42816137d8565b600060208451613ba39190614b0f565b15613c2a5760405162461bcd60e51b815260206004820152604b60248201527f4d65726b6c652e70726f63657373496e636c7573696f6e50726f6f664b65636360448201527f616b3a2070726f6f66206c656e6774682073686f756c642062652061206d756c60648201526a3a34b836329037b310199960a91b608482015260a401610778565b8260205b85518111610d1657613c41600285614b0f565b600003613c6557816000528086015160205260406000209150600284049350613c7e565b8086015160005281602052604060002091506002840493505b613c89602082614acb565b9050613c2e565b60008080600080516020615139833981519152600360008051602061513983398151915286600080516020615139833981519152888909090890506000613d06827f0c19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52600080516020615139833981519152613e9a565b91959194509092505050565b600061010082511115613d9b5760405162461bcd60e51b8152602060048201526044602482018190527f4269746d61705574696c732e6f72646572656442797465734172726179546f42908201527f69746d61703a206f7264657265644279746573417272617920697320746f6f206064820152636c6f6e6760e01b608482015260a401610778565b8151600003613dac57506000919050565b60008083600081518110613dc257613dc2614af9565b0160200151600160f89190911c81901b92505b8451811015613e9157848181518110613df057613df0614af9565b0160200151600160f89190911c1b9150828211613e855760405162461bcd60e51b815260206004820152604760248201527f4269746d61705574696c732e6f72646572656442797465734172726179546f4260448201527f69746d61703a206f72646572656442797465734172726179206973206e6f74206064820152661bdc99195c995960ca1b608482015260a401610778565b91811791600101613dd5565b50909392505050565b600080613ea5613fc3565b613ead613fe1565b602080825281810181905260408201819052606082018890526080820187905260a082018690528260c08360056107d05a03fa92508280613eea57fe5b5082613f385760405162461bcd60e51b815260206004820152601a60248201527f424e3235342e6578704d6f643a2063616c6c206661696c7572650000000000006044820152606401610778565b505195945050505050565b60405180606001604052806003906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b6040518060400160405280613f92613fff565b8152602001613f9f613fff565b905290565b604051806101800160405280600c906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b80356001600160601b031981168114613abf57600080fd5b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561406d5761406d614035565b60405290565b60405161010081016001600160401b038111828210171561406d5761406d614035565b604051601f8201601f191681016001600160401b03811182821017156140be576140be614035565b604052919050565b6000806001600160401b038411156140e0576140e0614035565b50601f8301601f19166020016140f581614096565b91505082815283838301111561410a57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261413257600080fd5b614141838335602085016140c6565b9392505050565b6001600160a01b038116811461100a57600080fd5b600080600080600080600080610100898b03121561417a57600080fd5b88359750602089013596506040890135955061419860608a0161401d565b94506080890135935060a08901356001600160401b038111156141ba57600080fd5b6141c68b828c01614121565b93505060c0890135915060e08901356141de81614148565b809150509295985092959890939650565b60006040828403121561420157600080fd5b61420961404b565b823581526020928301359281019290925250919050565b600082601f83011261423157600080fd5b61423961404b565b80604084018581111561424b57600080fd5b845b8181101561426557803584526020938401930161424d565b509095945050505050565b60006080828403121561428257600080fd5b61428a61404b565b90506142968383614220565b81526142a58360408401614220565b602082015292915050565b60008060008061012085870312156142c757600080fd5b843593506142d886602087016141ef565b92506142e78660608701614270565b91506142f68660e087016141ef565b905092959194509250565b60006020828403121561431357600080fd5b5035919050565b60006020828403121561432c57600080fd5b813561391281614148565b602080825282518282018190526000918401906040840190835b818110156142655783516001600160a01b0316835260209384019390920191600101614351565b801515811461100a57600080fd5b60006020828403121561439857600080fd5b813561391281614378565b803563ffffffff81168114613abf57600080fd5b60006001600160401b038211156143d0576143d0614035565b5060051b60200190565b600082601f8301126143eb57600080fd5b81356143fe6143f9826143b7565b614096565b8082825260208201915060208360051b86010192508583111561442057600080fd5b602085015b8381101561444457614436816143a3565b835260209283019201614425565b5095945050505050565b600082601f83011261445f57600080fd5b813561446d6143f9826143b7565b8082825260208201915060208360061b86010192508583111561448f57600080fd5b602085015b83811015614444576144a687826141ef565b8352602090920191604001614494565b600082601f8301126144c757600080fd5b81356144d56143f9826143b7565b8082825260208201915060208360051b8601019250858311156144f757600080fd5b602085015b838110156144445780356001600160401b0381111561451a57600080fd5b614529886020838a01016143da565b845250602092830192016144fc565b6000610180828403121561454b57600080fd5b614553614073565b905081356001600160401b0381111561456b57600080fd5b614577848285016143da565b82525060208201356001600160401b0381111561459357600080fd5b61459f8482850161444e565b60208301525060408201356001600160401b038111156145be57600080fd5b6145ca8482850161444e565b6040830152506145dd8360608401614270565b60608201526145ef8360e084016141ef565b60808201526101208201356001600160401b0381111561460e57600080fd5b61461a848285016143da565b60a0830152506101408201356001600160401b0381111561463a57600080fd5b614646848285016143da565b60c0830152506101608201356001600160401b0381111561466657600080fd5b614672848285016144b6565b60e08301525092915050565b60008060006060848603121561469357600080fd5b833592506146a3602085016143a3565b915060408401356001600160401b038111156146be57600080fd5b6146ca86828701614538565b9150509250925092565b600081518084526020840193506020830160005b8281101561470f5781516001600160601b03168652602095860195909101906001016146e8565b5093949350505050565b604081526000835160408084015261473460808401826146d4565b90506020850151603f1984830301606085015261475182826146d4565b925050508260208301529392505050565b60008083601f84011261477457600080fd5b5081356001600160401b0381111561478b57600080fd5b6020830191508360208285010111156147a357600080fd5b9250929050565b6000806000604084860312156147bf57600080fd5b83356001600160401b038111156147d557600080fd5b6147e186828701614762565b909790965060209590950135949350505050565b6000806040838503121561480857600080fd5b823561481381614148565b915060208301356001600160401b0381111561482e57600080fd5b83016060818603121561484057600080fd5b604051606081016001600160401b038111828210171561486257614862614035565b60405281356001600160401b0381111561487b57600080fd5b61488787828501614121565b8252506020828101359082015260409182013591810191909152919491935090915050565b6000602082840312156148be57600080fd5b81356001600160401b038111156148d457600080fd5b8201601f810184136148e557600080fd5b6148f4848235602084016140c6565b949350505050565b60008060006060848603121561491157600080fd5b8335925060208401356146a381614148565b60008060006060848603121561493857600080fd5b833561494381614148565b9250602084013561495381614148565b9150604084013561496381614148565b809150509250925092565b6000806000806060858703121561498457600080fd5b8435935060208501356001600160401b038111156149a157600080fd5b6149ad87828801614762565b9598909750949560400135949350505050565b600080600080600080600060e0888a0312156149db57600080fd5b8735965060208801359550604088013594506149f96060890161401d565b93506080880135925060a08801356001600160401b03811115614a1b57600080fd5b614a278a828b01614121565b979a969950949793969295929450505060c09091013590565b60008060208385031215614a5357600080fd5b82356001600160401b03811115614a6957600080fd5b8301601f81018513614a7a57600080fd5b80356001600160401b03811115614a9057600080fd5b8560208260051b8401011115614aa557600080fd5b6020919091019590945092505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561391557613915614ab5565b91825260601b6001600160601b031916602082015260340190565b634e487b7160e01b600052603260045260246000fd5b600082614b2c57634e487b7160e01b600052601260045260246000fd5b500690565b8181038181111561391557613915614ab5565b600060208284031215614b5657600080fd5b5051919050565b600060208284031215614b6f57600080fd5b81516001600160c01b038116811461391257600080fd5b600060208284031215614b9857600080fd5b815160ff8116811461391257600080fd5b6001600160601b038116811461100a57600080fd5b60006040828403128015614bd157600080fd5b50614bda61404b565b8251614be581614148565b81526020830151614bf581614ba9565b60208201529392505050565b600060018201614c1357614c13614ab5565b5060010190565b600060208284031215614c2c57600080fd5b815161391281614148565b600060208284031215614c4957600080fd5b815167ffffffffffffffff198116811461391257600080fd5b600060208284031215614c7457600080fd5b815161391281614ba9565b6001600160601b03828116828216039081111561391557613915614ab5565b63ffffffff60e01b8360e01b16815260006004820183516020850160005b82811015614cda578151845260209384019390910190600101614cbc565b50919695505050505050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b8183823760009101908152919050565b60208082526052908201527f536572766963654d616e61676572426173652e6f6e6c7952656769737472794360408201527f6f6f7264696e61746f723a2063616c6c6572206973206e6f742074686520726560608201527133b4b9ba393c9031b7b7b93234b730ba37b960711b608082015260a00190565b6000815180845260005b81811015614de257602081850181015186830182015201614dc6565b506000602082860101526020601f19601f83011685010191505092915050565b60018060a01b0383168152604060208201526000825160606040840152614e2c60a0840182614dbc565b90506020840151606084015260408401516080840152809150509392505050565b6020815260006141416020830184614dbc565b6001600160601b038181168382160290811690818114614e8257614e82614ab5565b5092915050565b808202811582820484141761391557613915614ab5565b6001600160a01b038616815263ffffffff851660208201526080604082018190528101839052828460a0830137600060a08483010152600060a0601f19601f86011683010190508260608301529695505050505050565b8881528760208201528660408201526001600160601b03198616606082015284608082015261010060a08201526000614f34610100830186614dbc565b60c0830194909452506001600160a01b039190911660e0909101529695505050505050565b600060208284031215614f6b57600080fd5b815161391281614378565b60008235609e19833603018112614f8c57600080fd5b9190910192915050565b8035613abf81614148565b81835260208301925060008160005b8481101561470f578135614fc381614148565b6001600160a01b031686526020820135614fdc81614ba9565b6001600160601b031660208701526040958601959190910190600101614fb0565b6020808252810182905260006040600584901b830181019083018583609e1936839003015b8782101561510a57868503603f19018452823581811261504157600080fd5b8901803536829003601e1901811261505857600080fd5b81016020810190356001600160401b0381111561507457600080fd5b8060061b360382131561508657600080fd5b60a0885261509860a089018284614fa1565b9150506150a760208301614f96565b6001600160a01b03166020880152604082810135908801526150cb606083016143a3565b63ffffffff1660608801526150e2608083016143a3565b63ffffffff811660808901529150955050602093840193929092019160019190910190615022565b5092979650505050505050565b600061ffff821661ffff810361512f5761512f614ab5565b6001019291505056fe30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd470ea46f246ccfc58f7a93aa09bc6245a6818e97b1a160d186afe78993a3b194a0424c535369676e6174757265436865636b65722e636865636b5369676e617475a26469706673582212207210c68cfe53fd9c97ae16a9b75b1200d708eaca267e117065cd4e3550b21b3b64736f6c634300081a0033", + Bin: "0x6101806040523480156200001257600080fd5b506040516200561d3803806200561d8339810160408190526200003591620002e5565b6001600160a01b0380851660805280841660a05280831660c052811660e0528184848284620000636200020a565b50505050806001600160a01b0316610100816001600160a01b031681525050806001600160a01b031663683048356040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000c1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000e791906200034d565b6001600160a01b0316610120816001600160a01b031681525050806001600160a01b0316635df459466040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000140573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016691906200034d565b6001600160a01b0316610140816001600160a01b031681525050610120516001600160a01b031663df5cf7236040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001c2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001e891906200034d565b6001600160a01b03166101605250620002006200020a565b5050505062000374565b600054610100900460ff1615620002775760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161015620002ca576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b0381168114620002e257600080fd5b50565b60008060008060808587031215620002fc57600080fd5b84516200030981620002cc565b60208601519094506200031c81620002cc565b60408601519093506200032f81620002cc565b60608601519092506200034281620002cc565b939692955090935050565b6000602082840312156200036057600080fd5b81516200036d81620002cc565b9392505050565b60805160a05160c05160e0516101005161012051610140516101605161519b620004826000396000818161065401526117dd01526000818161039701526119f00152600081816103cb01528181611bdd0152611dcd0152600081816104320152818161100f015281816114a30152818161164a0152611891015260008181610d4401528181610e9501528181610f2c01528181612a7001528181612be90152612c88015260008181610b6b01528181610bfa01528181610c7a0152818161216601528181612232015281816129ab0152612b4401526000818161303f015281816130fb01526131de0152600081816103fc015281816121ba0152818161228e015261230d015261519b6000f3fe6080604052600436106101fd5760003560e01c806395c6d6041161010d578063d66eaabd116100a0578063f474b5201161006f578063f474b520146106ab578063f9120af6146106d8578063fa534dc0146106f8578063fc299dee14610718578063fce36c7d1461073857600080fd5b8063d66eaabd1461062f578063df5cf72314610642578063e481af9d14610676578063f2fde38b1461068b57600080fd5b8063ab21739a116100dc578063ab21739a1461056b578063b099627e1461058b578063b98d0908146105f5578063c0c53b8b1461060f57600080fd5b806395c6d604146104eb5780639926ee7d1461050b578063a364f4da1461052b578063a98fb3551461054b57600080fd5b80634ae07c37116101905780636d14a9871161015f5780636d14a9871461042057806370a0823114610454578063715018a614610498578063800fb61f146104ad5780638da5cb5b146104cd57600080fd5b80634ae07c37146103575780635df459461461038557806368304835146103b95780636b3aa72e146103ed57600080fd5b80633bc28c8c116101cc5780633bc28c8c146102cc578063416c7e5e146102ec5780634223d5511461030c5780634a5bf6321461031f57600080fd5b806306045a9114610213578063171f1d5b146102485780632e1a7d4d1461027f57806333cfb7b71461029f57600080fd5b3661020e5761020c3334610758565b005b600080fd5b34801561021f57600080fd5b5061023361022e366004614159565b6107ed565b60405190151581526020015b60405180910390f35b34801561025457600080fd5b506102686102633660046142ab565b6108e4565b60408051921515835290151560208301520161023f565b34801561028b57600080fd5b5061020c61029a3660046142fc565b610a6e565b3480156102ab57600080fd5b506102bf6102ba366004614315565b610b46565b60405161023f9190614332565b3480156102d857600080fd5b5061020c6102e7366004614315565b610ff9565b3480156102f857600080fd5b5061020c61030736600461438d565b61100d565b61020c61031a366004614315565b611144565b34801561032b57600080fd5b5060cb5461033f906001600160a01b031681565b6040516001600160a01b03909116815260200161023f565b34801561036357600080fd5b50610377610372366004614668565b61114e565b60405161023f929190614703565b34801561039157600080fd5b5061033f7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103c557600080fd5b5061033f7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103f957600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061033f565b34801561042c57600080fd5b5061033f7f000000000000000000000000000000000000000000000000000000000000000081565b34801561046057600080fd5b5061048a61046f366004614315565b6001600160a01b0316600090815260ca602052604090205490565b60405190815260200161023f565b3480156104a457600080fd5b5061020c612082565b3480156104b957600080fd5b5061020c6104c8366004614315565b612096565b3480156104d957600080fd5b506033546001600160a01b031661033f565b3480156104f757600080fd5b50610233610506366004614794565b612136565b34801561051757600080fd5b5061020c6105263660046147df565b61215b565b34801561053757600080fd5b5061020c610546366004614315565b612227565b34801561055757600080fd5b5061020c61056636600461488a565b6122ee565b34801561057757600080fd5b5061020c6105863660046148da565b612342565b34801561059757600080fd5b506105d36105a63660046142fc565b60c9602052600090815260409020805460019091015463ffffffff821691640100000000900460ff169083565b6040805163ffffffff909416845291151560208401529082015260600161023f565b34801561060157600080fd5b506097546102339060ff1681565b34801561061b57600080fd5b5061020c61062a366004614901565b612701565b61020c61063d36600461494c565b6127eb565b34801561064e57600080fd5b5061033f7f000000000000000000000000000000000000000000000000000000000000000081565b34801561068257600080fd5b506102bf6129a5565b34801561069757600080fd5b5061020c6106a6366004614315565b612d51565b3480156106b757600080fd5b5061048a6106c6366004614315565b60ca6020526000908152604090205481565b3480156106e457600080fd5b5061020c6106f3366004614315565b612dc7565b34801561070457600080fd5b5061023361071336600461499e565b612df1565b34801561072457600080fd5b5060655461033f906001600160a01b031681565b34801561074457600080fd5b5061020c610753366004614a1b565b612e66565b8060000361078157604051632097692160e11b8152600481018290526024015b60405180910390fd5b6001600160a01b038216600090815260ca6020526040812080548392906107a9908490614aa5565b90915550506001600160a01b038216600081815260ca6020908152604091829020549151918252600080516020615126833981519152910160405180910390a25050565b6000806001600160a01b038316610805575084610831565b8583604051602001610818929190614ab8565b6040516020818303038152906040528051906020012090505b600081815260c9602052604081205463ffffffff1690036108565760009150506108d8565b600081815260c96020526040902054640100000000900460ff1661087e5760009150506108d8565b60408051602081018c90529081018a9052606081018990526001600160601b03198816608082015260009060940160408051601f19818403018152919052805160208201209091506108d287898389613215565b93505050505b98975050505050505050565b60008060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018787600001518860200151886000015160006002811061092c5761092c614ad3565b60200201518951600160200201518a6020015160006002811061095157610951614ad3565b60200201518b6020015160016002811061096d5761096d614ad3565b602090810291909101518c518d8301516040516109ca9a99989796959401988952602089019790975260408801959095526060870193909352608086019190915260a085015260c084015260e08301526101008201526101200190565b6040516020818303038152906040528051906020012060001c6109ed9190614ae9565b9050610a60610a066109ff888461322d565b86906132be565b610a0e613353565b610a56610a4785610a41604080518082018252600080825260209182015281518083019092526001825260029082015290565b9061322d565b610a508c613413565b906132be565b886201d4c06134a2565b909890975095505050505050565b33600090815260ca6020526040902054811115610abf5733600081815260ca602052604090819020549051632e2a182f60e11b81526004810192909252602482018390526044820152606401610778565b33600090815260ca602052604081208054839290610ade908490614b0b565b909155505033600081815260ca6020908152604091829020549151918252600080516020615126833981519152910160405180910390a2604051339082156108fc029083906000818181858888f19350505050158015610b42573d6000803e3d6000fd5b5050565b6040516309aa152760e11b81526001600160a01b0382811660048301526060916000917f000000000000000000000000000000000000000000000000000000000000000016906313542a4e90602401602060405180830381865afa158015610bb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd69190614b1e565b60405163871ef04960e01b8152600481018290529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063871ef04990602401602060405180830381865afa158015610c41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c659190614b37565b90506001600160c01b0381161580610cff57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639aa1653d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfa9190614b60565b60ff16155b15610d1f5760408051600080825260208201909252905b50949350505050565b6000610d33826001600160c01b03166136bc565b90506000805b8251811015610dff577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633ca5a5f5848381518110610d8357610d83614ad3565b01602001516040516001600160e01b031960e084901b16815260f89190911c6004820152602401602060405180830381865afa158015610dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610deb9190614b1e565b610df59083614aa5565b9150600101610d39565b506000816001600160401b03811115610e1a57610e1a614035565b604051908082528060200260200182016040528015610e43578160200160208202803683370190505b5090506000805b8451811015610fec576000858281518110610e6757610e67614ad3565b0160200151604051633ca5a5f560e01b815260f89190911c6004820181905291506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633ca5a5f590602401602060405180830381865afa158015610edc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f009190614b1e565b905060005b81811015610fe1576040516356e4026d60e11b815260ff84166004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063adc804da906044016040805180830381865afa158015610f7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9e9190614b98565b60000151868681518110610fb457610fb4614ad3565b6001600160a01b039092166020928302919091019091015284610fd681614bd9565b955050600101610f05565b505050600101610e4a565b5090979650505050505050565b61100161377e565b61100a816137d8565b50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561106b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108f9190614bf2565b6001600160a01b0316336001600160a01b03161461113b5760405162461bcd60e51b815260206004820152605c60248201527f424c535369676e6174757265436865636b65722e6f6e6c79436f6f7264696e6160448201527f746f724f776e65723a2063616c6c6572206973206e6f7420746865206f776e6560648201527f72206f6620746865207265676973747279436f6f7264696e61746f7200000000608482015260a401610778565b61100a81613841565b61100a8134610758565b604080518082019091526060808252602082015260008260400151516040518060400160405280600181526020016000815250511480156111aa57508260a0015151604051806040016040528060018152602001600081525051145b80156111d157508260c0015151604051806040016040528060018152602001600081525051145b80156111f857508260e0015151604051806040016040528060018152602001600081525051145b6112625760405162461bcd60e51b8152602060048201526041602482015260008051602061514683398151915260448201527f7265733a20696e7075742071756f72756d206c656e677468206d69736d6174636064820152600d60fb1b608482015260a401610778565b825151602084015151146112da5760405162461bcd60e51b815260206004820152604460248201819052600080516020615146833981519152908201527f7265733a20696e707574206e6f6e7369676e6572206c656e677468206d69736d6064820152630c2e8c6d60e31b608482015260a401610778565b4363ffffffff168463ffffffff16106113495760405162461bcd60e51b815260206004820152603c602482015260008051602061514683398151915260448201527f7265733a20696e76616c6964207265666572656e636520626c6f636b000000006064820152608401610778565b60408051808201825260008082526020808301829052835180850185526060808252818301528451808601865260018082529083019390935284518381528086019095529293919082810190803683370190505060208281019190915260408051808201825260018082526000919093015280518281528082019091529081602001602082028036833701905050815260408051808201909152606080825260208201528560200151516001600160401b0381111561140a5761140a614035565b604051908082528060200260200182016040528015611433578160200160208202803683370190505b5081526020860151516001600160401b0381111561145357611453614035565b60405190808252806020026020018201604052801561147c578160200160208202803683370190505b508160200181905250600061152860405180604001604052806001815260200160008152507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639aa1653d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115239190614b60565b613888565b905060005b8760200151518110156117b9576115728860200151828151811061155357611553614ad3565b6020026020010151805160009081526020918201519091526040902090565b8360200151828151811061158857611588614ad3565b602090810291909101015280156116485760208301516115a9600183614b0b565b815181106115b9576115b9614ad3565b602002602001015160001c836020015182815181106115da576115da614ad3565b602002602001015160001c11611648576040805162461bcd60e51b815260206004820152602481019190915260008051602061514683398151915260448201527f7265733a206e6f6e5369676e65725075626b657973206e6f7420736f727465646064820152608401610778565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166304ec63518460200151838151811061168d5761168d614ad3565b60200260200101518b8b6000015185815181106116ac576116ac614ad3565b60200260200101516040518463ffffffff1660e01b81526004016116e99392919092835263ffffffff918216602084015216604082015260600190565b602060405180830381865afa158015611706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172a9190614b37565b6001600160c01b03168360000151828151811061174957611749614ad3565b6020026020010181815250506117af6109ff611783848660000151858151811061177557611775614ad3565b60200260200101511661391b565b8a60200151848151811061179957611799614ad3565b602002602001015161394690919063ffffffff16565b945060010161152d565b50506117c483613a29565b60975490935060ff166000816117db57600061185d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c448feb86040518163ffffffff1660e01b8152600401602060405180830381865afa158015611839573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185d9190614b1e565b905060005b604051806040016040528060018152602001600081525051811015611f535782156119ee578963ffffffff16827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663249a0c42604051806040016040528060018152602001600081525085815181106118e6576118e6614ad3565b01602001516040516001600160e01b031960e084901b16815260f89190911c6004820152602401602060405180830381865afa15801561192a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194e9190614b1e565b6119589190614aa5565b116119ee5760405162461bcd60e51b8152602060048201526066602482015260008051602061514683398151915260448201527f7265733a205374616b6552656769737472792075706461746573206d7573742060648201527f62652077697468696e207769746864726177616c44656c6179426c6f636b732060848201526577696e646f7760d01b60a482015260c401610778565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166368bccaac60405180604001604052806001815260200160008152508381518110611a4557611a45614ad3565b602001015160f81c60f81b60f81c8c8c60a001518581518110611a6a57611a6a614ad3565b60209081029190910101516040516001600160e01b031960e086901b16815260ff909316600484015263ffffffff9182166024840152166044820152606401602060405180830381865afa158015611ac6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aea9190614c0f565b6001600160401b031916611b0d8a60400151838151811061155357611553614ad3565b67ffffffffffffffff191614611ba95760405162461bcd60e51b8152602060048201526061602482015260008051602061514683398151915260448201527f7265733a2071756f72756d41706b206861736820696e2073746f72616765206460648201527f6f6573206e6f74206d617463682070726f76696465642071756f72756d2061706084820152606b60f81b60a482015260c401610778565b611bd989604001518281518110611bc257611bc2614ad3565b6020026020010151876132be90919063ffffffff16565b95507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c8294c5660405180604001604052806001815260200160008152508381518110611c3257611c32614ad3565b602001015160f81c60f81b60f81c8c8c60c001518581518110611c5757611c57614ad3565b60209081029190910101516040516001600160e01b031960e086901b16815260ff909316600484015263ffffffff9182166024840152166044820152606401602060405180830381865afa158015611cb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd79190614c3a565b85602001518281518110611ced57611ced614ad3565b6001600160601b03909216602092830291909101820152850151805182908110611d1957611d19614ad3565b602002602001015185600001518281518110611d3757611d37614ad3565b60200260200101906001600160601b031690816001600160601b0316815250506000805b8a6020015151811015611f4957611dc686600001518281518110611d8157611d81614ad3565b602002602001015160405180604001604052806001815260200160008152508581518110611db157611db1614ad3565b016020015160f81c60ff161c60019081161490565b15611f41577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f2be94ae60405180604001604052806001815260200160008152508581518110611e2257611e22614ad3565b602001015160f81c60f81b60f81c8e89602001518581518110611e4757611e47614ad3565b60200260200101518f60e001518881518110611e6557611e65614ad3565b60200260200101518781518110611e7e57611e7e614ad3565b60209081029190910101516040516001600160e01b031960e087901b16815260ff909416600485015263ffffffff92831660248501526044840191909152166064820152608401602060405180830381865afa158015611ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f069190614c3a565b8751805185908110611f1a57611f1a614ad3565b60200260200101818151611f2e9190614c57565b6001600160601b03169052506001909101905b600101611d5b565b5050600101611862565b505050600080611f6d8a868a606001518b608001516108e4565b9150915081611fde5760405162461bcd60e51b8152602060048201526043602482015260008051602061514683398151915260448201527f7265733a2070616972696e6720707265636f6d70696c652063616c6c206661696064820152621b195960ea1b608482015260a401610778565b8061203f5760405162461bcd60e51b8152602060048201526039602482015260008051602061514683398151915260448201527f7265733a207369676e617475726520697320696e76616c6964000000000000006064820152608401610778565b5050600087826020015160405160200161205a929190614c7e565b60408051808303601f1901815291905280516020909101209299929850919650505050505050565b61208a61377e565b6120946000613ac4565b565b600054600290610100900460ff161580156120b8575060005460ff8083169116105b6120d45760405162461bcd60e51b815260040161077890614cc6565b6000805461ffff191660ff8316176101001790556120f182612dc7565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6000818484604051612149929190614d14565b60405180910390201490509392505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146121a35760405162461bcd60e51b815260040161077890614d24565b604051639926ee7d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639926ee7d906121f19085908590600401614de2565b600060405180830381600087803b15801561220b57600080fd5b505af115801561221f573d6000803e3d6000fd5b505050505050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461226f5760405162461bcd60e51b815260040161077890614d24565b6040516351b27a6d60e11b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063a364f4da906024015b600060405180830381600087803b1580156122d357600080fd5b505af11580156122e7573d6000803e3d6000fd5b5050505050565b6122f661377e565b60405163a98fb35560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a98fb355906122b9908490600401614e2d565b60cb546001600160a01b031633146123825760cb54604051632cbe419560e01b81523360048201526001600160a01b039091166024820152604401610778565b60005a90506000848460405160200161239c929190614ab8565b60408051601f198184030181529181528151602092830120600081815260c990935290822080549193509163ffffffff90911690036123f1576040516311cb69a760e11b815260048101839052602401610778565b8054640100000000900460ff161561241f57604051634e78d7f960e11b815260048101839052602401610778565b805464ff00000000191664010000000017815560018101546001600160a01b038616600090815260ca602052604090205410156124a25760018101546001600160a01b038616600081815260ca602052604090819020549051632e2a182f60e11b8152600481019290925260248201929092526044810191909152606401610778565b80546000906124b990849063ffffffff168761114e565b509050604360ff1681602001516000815181106124d8576124d8614ad3565b60200260200101516124ea9190614e40565b6001600160601b03166064826000015160008151811061250c5761250c614ad3565b60200260200101516001600160601b03166125279190614e63565b10156125ba576064816000015160008151811061254657612546614ad3565b60200260200101516001600160601b03166125619190614e63565b604360ff16826020015160008151811061257d5761257d614ad3565b602002602001015161258f9190614e40565b60405163530f5c4560e11b815260048101929092526001600160601b03166024820152604401610778565b6040516001600160a01b038716815287907f8511746b73275e06971968773119b9601fc501d7bdf3824d8754042d148940e29060200160405180910390a260003a5a6126069087614b0b565b6126139062011170614aa5565b61261d9190614e63565b9050826001015481111561265457600183015460405163437e283f60e11b8152600481019190915260248101829052604401610778565b6001600160a01b038716600090815260ca60205260408120805483929061267c908490614b0b565b90915550506001600160a01b038716600081815260ca6020908152604091829020549151918252600080516020615126833981519152910160405180910390a260cb546040516001600160a01b039091169082156108fc029083906000818181858888f193505050501580156126f6573d6000803e3d6000fd5b505050505050505050565b600054610100900460ff16158080156127215750600054600160ff909116105b8061273b5750303b15801561273b575060005460ff166001145b6127575760405162461bcd60e51b815260040161077890614cc6565b6000805460ff19166001179055801561277a576000805461ff0019166101001790555b6127848484613b16565b60cb80546001600160a01b0319166001600160a01b03841617905580156127e5576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b60008433604051602001612800929190614ab8565b60408051601f198184030181529181528151602092830120600081815260c990935291205490915063ffffffff161561284f57604051630c40bc4360e21b815260048101829052602401610778565b34156128ac5733600090815260ca602052604081208054349290612874908490614aa5565b909155505033600081815260ca6020908152604091829020549151918252600080516020615126833981519152910160405180910390a25b33600090815260ca60205260409020548211156128fd5733600081815260ca602052604090819020549051632e2a182f60e11b81526004810192909252602482018490526044820152606401610778565b604080516060810182526000602080830182815263ffffffff43818116865285870189815288865260c99094529386902085518154935115156401000000000264ffffffffff1990941692169190911791909117815590516001909101559151909187917f8801fc966deb2c8f563a103c35c9e80740585c292cd97518587e6e7927e6af5591612995913391908a908a908a90614e7a565b60405180910390a2505050505050565b606060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639aa1653d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2b9190614b60565b60ff16905080600003612a4c57505060408051600081526020810190915290565b6000805b82811015612af757604051633ca5a5f560e01b815260ff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633ca5a5f590602401602060405180830381865afa158015612abf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae39190614b1e565b612aed9083614aa5565b9150600101612a50565b506000816001600160401b03811115612b1257612b12614035565b604051908082528060200260200182016040528015612b3b578160200160208202803683370190505b5090506000805b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639aa1653d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc49190614b60565b60ff16811015612d4757604051633ca5a5f560e01b815260ff821660048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690633ca5a5f590602401602060405180830381865afa158015612c38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5c9190614b1e565b905060005b81811015612d3d576040516356e4026d60e11b815260ff84166004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063adc804da906044016040805180830381865afa158015612cd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cfa9190614b98565b60000151858581518110612d1057612d10614ad3565b6001600160a01b039092166020928302919091019091015283612d3281614bd9565b945050600101612c61565b5050600101612b42565b5090949350505050565b612d5961377e565b6001600160a01b038116612dbe5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610778565b61100a81613ac4565b612dcf61377e565b60cb80546001600160a01b0319166001600160a01b0392909216919091179055565b6040516306045a9160e01b815260009030906306045a9190612e25908b908b908b908b908b908b908b908b90600401614ed1565b602060405180830381865afa158015612e42573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d89190614f33565b6065546001600160a01b03163314612efb5760405162461bcd60e51b815260206004820152604c60248201527f536572766963654d616e61676572426173652e6f6e6c7952657761726473496e60448201527f69746961746f723a2063616c6c6572206973206e6f742074686520726577617260648201526b32399034b734ba34b0ba37b960a11b608482015260a401610778565b60005b818110156131c657828282818110612f1857612f18614ad3565b9050602002810190612f2a9190614f50565b612f3b906040810190602001614315565b6001600160a01b03166323b872dd3330868686818110612f5d57612f5d614ad3565b9050602002810190612f6f9190614f50565b604080516001600160e01b031960e087901b1681526001600160a01b039485166004820152939092166024840152013560448201526064016020604051808303816000875af1158015612fc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fea9190614f33565b506000838383818110612fff57612fff614ad3565b90506020028101906130119190614f50565b613022906040810190602001614315565b604051636eb1769f60e11b81523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152919091169063dd62ed3e90604401602060405180830381865afa158015613090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130b49190614b1e565b90508383838181106130c8576130c8614ad3565b90506020028101906130da9190614f50565b6130eb906040810190602001614315565b6001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000008387878781811061312d5761312d614ad3565b905060200281019061313f9190614f50565b6040013561314d9190614aa5565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015613198573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131bc9190614f33565b5050600101612efe565b5060405163fce36c7d60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063fce36c7d906121f19085908590600401614fd6565b600083613223868585613b93565b1495945050505050565b6040805180820190915260008082526020820152613249613f43565b835181526020808501519082015260408082018490526000908360608460076107d05a03fa9050808061327857fe5b50806132b65760405162461bcd60e51b815260206004820152600d60248201526c1958cb5b5d5b0b59985a5b1959609a1b6044820152606401610778565b505092915050565b60408051808201909152600080825260208201526132da613f61565b835181526020808501518183015283516040808401919091529084015160608301526000908360808460066107d05a03fa9050808061331557fe5b50806132b65760405162461bcd60e51b815260206004820152600d60248201526c1958cb5859190b59985a5b1959609a1b6044820152606401610778565b61335b613f7f565b50604080516080810182527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c28183019081527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6060830152815281518083019092527f275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec82527f1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d60208381019190915281019190915290565b60408051808201909152600080825260208201526000808061344360008051602061510683398151915286614ae9565b90505b61344f81613c90565b90935091506000805160206151068339815191528283098303613488576040805180820190915290815260208101919091529392505050565b600080516020615106833981519152600182089050613446565b6040805180820182528681526020808201869052825180840190935286835282018490526000918291906134d4613fa4565b60005b600281101561368f5760006134ed826006614e63565b905084826002811061350157613501614ad3565b60200201515183613513836000614aa5565b600c811061352357613523614ad3565b602002015284826002811061353a5761353a614ad3565b602002015160200151838260016135519190614aa5565b600c811061356157613561614ad3565b602002015283826002811061357857613578614ad3565b602002015151518361358b836002614aa5565b600c811061359b5761359b614ad3565b60200201528382600281106135b2576135b2614ad3565b60200201515160016020020151836135cb836003614aa5565b600c81106135db576135db614ad3565b60200201528382600281106135f2576135f2614ad3565b60200201516020015160006002811061360d5761360d614ad3565b60200201518361361e836004614aa5565b600c811061362e5761362e614ad3565b602002015283826002811061364557613645614ad3565b60200201516020015160016002811061366057613660614ad3565b602002015183613671836005614aa5565b600c811061368157613681614ad3565b6020020152506001016134d7565b50613698613fc3565b60006020826101808560088cfa9151919c9115159b50909950505050505050505050565b60606000806136ca8461391b565b61ffff166001600160401b038111156136e5576136e5614035565b6040519080825280601f01601f19166020018201604052801561370f576020820181803683370190505b5090506000805b825182108015613727575061010081105b15612d47576001811b93508584161561376e578060f81b83838151811061375057613750614ad3565b60200101906001600160f81b031916908160001a9053508160010191505b61377781614bd9565b9050613716565b6033546001600160a01b031633146120945760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610778565b606554604080516001600160a01b03928316815291831660208301527fe11cddf1816a43318ca175bbc52cd0185436e9cbead7c83acc54a73e461717e3910160405180910390a1606580546001600160a01b0319166001600160a01b0392909216919091179055565b6097805460ff19168215159081179091556040519081527f40e4ed880a29e0f6ddce307457fb75cddf4feef7d3ecb0301bfdf4976a0e2dfc9060200160405180910390a150565b60008061389484613d12565b9050808360ff166001901b116139125760405162461bcd60e51b815260206004820152603f60248201527f4269746d61705574696c732e6f72646572656442797465734172726179546f4260448201527f69746d61703a206269746d61702065786365656473206d61782076616c7565006064820152608401610778565b90505b92915050565b6000805b821561391557613930600184614b0b565b909216918061393e816150e4565b91505061391f565b60408051808201909152600080825260208201526102008261ffff16106139a25760405162461bcd60e51b815260206004820152601060248201526f7363616c61722d746f6f2d6c6172676560801b6044820152606401610778565b8161ffff166001036139b5575081613915565b6040805180820190915260008082526020820181905284906001905b8161ffff168661ffff1610613a1e57600161ffff871660ff83161c81169003613a01576139fe84846132be565b93505b613a0b83846132be565b92506201fffe600192831b1691016139d1565b509195945050505050565b60408051808201909152600080825260208201528151158015613a4e57506020820151155b15613a6c575050604080518082019091526000808252602082015290565b6040518060400160405280836000015181526020016000805160206151068339815191528460200151613a9f9190614ae9565b613ab790600080516020615106833981519152614b0b565b905292915050565b919050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16613b815760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610778565b613b8a82613ac4565b610b42816137d8565b600060208451613ba39190614ae9565b15613c2a5760405162461bcd60e51b815260206004820152604b60248201527f4d65726b6c652e70726f63657373496e636c7573696f6e50726f6f664b65636360448201527f616b3a2070726f6f66206c656e6774682073686f756c642062652061206d756c60648201526a3a34b836329037b310199960a91b608482015260a401610778565b8260205b85518111610d1657613c41600285614ae9565b600003613c6557816000528086015160205260406000209150600284049350613c7e565b8086015160005281602052604060002091506002840493505b613c89602082614aa5565b9050613c2e565b60008080600080516020615106833981519152600360008051602061510683398151915286600080516020615106833981519152888909090890506000613d06827f0c19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52600080516020615106833981519152613e9a565b91959194509092505050565b600061010082511115613d9b5760405162461bcd60e51b8152602060048201526044602482018190527f4269746d61705574696c732e6f72646572656442797465734172726179546f42908201527f69746d61703a206f7264657265644279746573417272617920697320746f6f206064820152636c6f6e6760e01b608482015260a401610778565b8151600003613dac57506000919050565b60008083600081518110613dc257613dc2614ad3565b0160200151600160f89190911c81901b92505b8451811015613e9157848181518110613df057613df0614ad3565b0160200151600160f89190911c1b9150828211613e855760405162461bcd60e51b815260206004820152604760248201527f4269746d61705574696c732e6f72646572656442797465734172726179546f4260448201527f69746d61703a206f72646572656442797465734172726179206973206e6f74206064820152661bdc99195c995960ca1b608482015260a401610778565b91811791600101613dd5565b50909392505050565b600080613ea5613fc3565b613ead613fe1565b602080825281810181905260408201819052606082018890526080820187905260a082018690528260c08360056107d05a03fa92508280613eea57fe5b5082613f385760405162461bcd60e51b815260206004820152601a60248201527f424e3235342e6578704d6f643a2063616c6c206661696c7572650000000000006044820152606401610778565b505195945050505050565b60405180606001604052806003906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b6040518060400160405280613f92613fff565b8152602001613f9f613fff565b905290565b604051806101800160405280600c906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b80356001600160601b031981168114613abf57600080fd5b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561406d5761406d614035565b60405290565b60405161010081016001600160401b038111828210171561406d5761406d614035565b604051601f8201601f191681016001600160401b03811182821017156140be576140be614035565b604052919050565b60006001600160401b038311156140df576140df614035565b6140f2601f8401601f1916602001614096565b905082815283838301111561410657600080fd5b828260208301376000602084830101529392505050565b600082601f83011261412e57600080fd5b61413d838335602085016140c6565b9392505050565b6001600160a01b038116811461100a57600080fd5b600080600080600080600080610100898b03121561417657600080fd5b88359750602089013596506040890135955061419460608a0161401d565b94506080890135935060a08901356001600160401b038111156141b657600080fd5b6141c28b828c0161411d565b93505060c0890135915060e08901356141da81614144565b809150509295985092959890939650565b6000604082840312156141fd57600080fd5b61420561404b565b9050813581526020820135602082015292915050565b600082601f83011261422c57600080fd5b61423461404b565b80604084018581111561424657600080fd5b845b81811015614260578035845260209384019301614248565b509095945050505050565b60006080828403121561427d57600080fd5b61428561404b565b9050614291838361421b565b81526142a0836040840161421b565b602082015292915050565b60008060008061012085870312156142c257600080fd5b843593506142d386602087016141eb565b92506142e2866060870161426b565b91506142f18660e087016141eb565b905092959194509250565b60006020828403121561430e57600080fd5b5035919050565b60006020828403121561432757600080fd5b813561391281614144565b6020808252825182820181905260009190848201906040850190845b818110156143735783516001600160a01b03168352928401929184019160010161434e565b50909695505050505050565b801515811461100a57600080fd5b60006020828403121561439f57600080fd5b81356139128161437f565b803563ffffffff81168114613abf57600080fd5b60006001600160401b038211156143d7576143d7614035565b5060051b60200190565b600082601f8301126143f257600080fd5b81356020614407614402836143be565b614096565b8083825260208201915060208460051b87010193508684111561442957600080fd5b602086015b8481101561444c5761443f816143aa565b835291830191830161442e565b509695505050505050565b600082601f83011261446857600080fd5b81356020614478614402836143be565b8083825260208201915060208460061b87010193508684111561449a57600080fd5b602086015b8481101561444c576144b188826141eb565b83529183019160400161449f565b600082601f8301126144d057600080fd5b813560206144e0614402836143be565b82815260059290921b840181019181810190868411156144ff57600080fd5b8286015b8481101561444c5780356001600160401b038111156145225760008081fd5b6145308986838b01016143e1565b845250918301918301614503565b6000610180828403121561455157600080fd5b614559614073565b905081356001600160401b038082111561457257600080fd5b61457e858386016143e1565b8352602084013591508082111561459457600080fd5b6145a085838601614457565b602084015260408401359150808211156145b957600080fd5b6145c585838601614457565b60408401526145d7856060860161426b565b60608401526145e98560e086016141eb565b608084015261012084013591508082111561460357600080fd5b61460f858386016143e1565b60a084015261014084013591508082111561462957600080fd5b614635858386016143e1565b60c084015261016084013591508082111561464f57600080fd5b5061465c848285016144bf565b60e08301525092915050565b60008060006060848603121561467d57600080fd5b8335925061468d602085016143aa565b915060408401356001600160401b038111156146a857600080fd5b6146b48682870161453e565b9150509250925092565b60008151808452602080850194506020840160005b838110156146f85781516001600160601b0316875295820195908201906001016146d3565b509495945050505050565b604081526000835160408084015261471e60808401826146be565b90506020850151603f1984830301606085015261473b82826146be565b925050508260208301529392505050565b60008083601f84011261475e57600080fd5b5081356001600160401b0381111561477557600080fd5b60208301915083602082850101111561478d57600080fd5b9250929050565b6000806000604084860312156147a957600080fd5b83356001600160401b038111156147bf57600080fd5b6147cb8682870161474c565b909790965060209590950135949350505050565b600080604083850312156147f257600080fd5b82356147fd81614144565b915060208301356001600160401b038082111561481957600080fd5b908401906060828703121561482d57600080fd5b60405160608101818110838211171561484857614848614035565b60405282358281111561485a57600080fd5b6148668882860161411d565b82525060208301356020820152604083013560408201528093505050509250929050565b60006020828403121561489c57600080fd5b81356001600160401b038111156148b257600080fd5b8201601f810184136148c357600080fd5b6148d2848235602084016140c6565b949350505050565b6000806000606084860312156148ef57600080fd5b83359250602084013561468d81614144565b60008060006060848603121561491657600080fd5b833561492181614144565b9250602084013561493181614144565b9150604084013561494181614144565b809150509250925092565b6000806000806060858703121561496257600080fd5b8435935060208501356001600160401b0381111561497f57600080fd5b61498b8782880161474c565b9598909750949560400135949350505050565b600080600080600080600060e0888a0312156149b957600080fd5b8735965060208801359550604088013594506149d76060890161401d565b93506080880135925060a08801356001600160401b038111156149f957600080fd5b614a058a828b0161411d565b92505060c0880135905092959891949750929550565b60008060208385031215614a2e57600080fd5b82356001600160401b0380821115614a4557600080fd5b818501915085601f830112614a5957600080fd5b813581811115614a6857600080fd5b8660208260051b8501011115614a7d57600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561391557613915614a8f565b91825260601b6001600160601b031916602082015260340190565b634e487b7160e01b600052603260045260246000fd5b600082614b0657634e487b7160e01b600052601260045260246000fd5b500690565b8181038181111561391557613915614a8f565b600060208284031215614b3057600080fd5b5051919050565b600060208284031215614b4957600080fd5b81516001600160c01b038116811461391257600080fd5b600060208284031215614b7257600080fd5b815160ff8116811461391257600080fd5b6001600160601b038116811461100a57600080fd5b600060408284031215614baa57600080fd5b614bb261404b565b8251614bbd81614144565b81526020830151614bcd81614b83565b60208201529392505050565b600060018201614beb57614beb614a8f565b5060010190565b600060208284031215614c0457600080fd5b815161391281614144565b600060208284031215614c2157600080fd5b815167ffffffffffffffff198116811461391257600080fd5b600060208284031215614c4c57600080fd5b815161391281614b83565b6001600160601b03828116828216039080821115614c7757614c77614a8f565b5092915050565b63ffffffff60e01b8360e01b1681526000600482018351602080860160005b83811015614cb957815185529382019390820190600101614c9d565b5092979650505050505050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b8183823760009101908152919050565b60208082526052908201527f536572766963654d616e61676572426173652e6f6e6c7952656769737472794360408201527f6f6f7264696e61746f723a2063616c6c6572206973206e6f742074686520726560608201527133b4b9ba393c9031b7b7b93234b730ba37b960711b608082015260a00190565b6000815180845260005b81811015614dc257602081850181015186830182015201614da6565b506000602082860101526020601f19601f83011685010191505092915050565b60018060a01b0383168152604060208201526000825160606040840152614e0c60a0840182614d9c565b90506020840151606084015260408401516080840152809150509392505050565b60208152600061413d6020830184614d9c565b6001600160601b038181168382160280821691908281146132b6576132b6614a8f565b808202811582820484141761391557613915614a8f565b6001600160a01b038616815263ffffffff851660208201526080604082018190528101839052828460a0830137600060a08483010152600060a0601f19601f86011683010190508260608301529695505050505050565b60006101008a83528960208401528860408401526001600160601b0319881660608401528660808401528060a0840152614f0d81840187614d9c565b60c084019590955250506001600160a01b039190911660e0909101529695505050505050565b600060208284031215614f4557600080fd5b81516139128161437f565b60008235609e19833603018112614f6657600080fd5b9190910192915050565b8035613abf81614144565b8183526000602080850194508260005b858110156146f8578135614f9e81614144565b6001600160a01b0316875281830135614fb681614b83565b6001600160601b0316878401526040968701969190910190600101614f8b565b60208082528181018390526000906040808401600586901b8501820187855b888110156150d657878303603f190184528135368b9003609e1901811261501b57600080fd5b8a0160a0813536839003601e1901811261503457600080fd5b820188810190356001600160401b0381111561504f57600080fd5b8060061b360382131561506157600080fd5b8287526150718388018284614f7b565b92505050615080888301614f70565b6001600160a01b031688860152818701358786015260606150a28184016143aa565b63ffffffff169086015260806150b98382016143aa565b63ffffffff16950194909452509285019290850190600101614ff5565b509098975050505050505050565b600061ffff8083168181036150fb576150fb614a8f565b600101939250505056fe30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd470ea46f246ccfc58f7a93aa09bc6245a6818e97b1a160d186afe78993a3b194a0424c535369676e6174757265436865636b65722e636865636b5369676e617475a264697066735822122017381a449597ef4922b265b1d7131ee36bc696eb6b14b71efceea2c44e79114764736f6c63430008180033", } // ContractAlignedLayerServiceManagerABI is the input ABI used to generate the binding from. diff --git a/contracts/bindings/ERC20Mock/binding.go b/contracts/bindings/ERC20Mock/binding.go index 697fecbf1..237b5aa71 100644 --- a/contracts/bindings/ERC20Mock/binding.go +++ b/contracts/bindings/ERC20Mock/binding.go @@ -32,7 +32,7 @@ var ( // ContractERC20MockMetaData contains all meta data concerning the ContractERC20Mock contract. var ContractERC20MockMetaData = &bind.MetaData{ ABI: "[{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"mint\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false}]", - Bin: "0x6080604052348015600f57600080fd5b506105298061001f6000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806340c10f191161005b57806340c10f19146100cf57806370a08231146100e4578063a9059cbb1461010d578063dd62ed3e1461012057600080fd5b8063095ea7b31461008257806318160ddd146100aa57806323b872dd146100bc575b600080fd5b610095610090366004610416565b610159565b60405190151581526020015b60405180910390f35b6002545b6040519081526020016100a1565b6100956100ca366004610440565b610162565b6100e26100dd366004610416565b610179565b005b6100ae6100f236600461047d565b6001600160a01b031660009081526020819052604090205490565b61009561011b366004610416565b610187565b6100ae61012e36600461049f565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60015b92915050565b600061016f848484610191565b5060019392505050565b610183828261033b565b5050565b60003361016f8185855b6001600160a01b0383166101fa5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084015b60405180910390fd5b6001600160a01b03821661025c5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016101f1565b6001600160a01b0383166000908152602081905260409020548111156102d35760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016101f1565b6001600160a01b038381166000818152602081815260408083208054879003905593861680835291849020805486019055925184815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b6001600160a01b0382166103915760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016101f1565b80600260008282546103a391906104d2565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b80356001600160a01b038116811461041157600080fd5b919050565b6000806040838503121561042957600080fd5b610432836103fa565b946020939093013593505050565b60008060006060848603121561045557600080fd5b61045e846103fa565b925061046c602085016103fa565b929592945050506040919091013590565b60006020828403121561048f57600080fd5b610498826103fa565b9392505050565b600080604083850312156104b257600080fd5b6104bb836103fa565b91506104c9602084016103fa565b90509250929050565b8082018082111561015c57634e487b7160e01b600052601160045260246000fdfea2646970667358221220eaf8750f9edd283d7017b14cf9eef781f36ede2f73b9839d0a58bd01962b713064736f6c634300081a0033", + Bin: "0x608060405234801561001057600080fd5b50610528806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806340c10f191161005b57806340c10f19146100cf57806370a08231146100e4578063a9059cbb1461010d578063dd62ed3e1461012057600080fd5b8063095ea7b31461008257806318160ddd146100aa57806323b872dd146100bc575b600080fd5b610095610090366004610416565b610159565b60405190151581526020015b60405180910390f35b6002545b6040519081526020016100a1565b6100956100ca366004610440565b610162565b6100e26100dd366004610416565b610179565b005b6100ae6100f236600461047c565b6001600160a01b031660009081526020819052604090205490565b61009561011b366004610416565b610187565b6100ae61012e36600461049e565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60015b92915050565b600061016f848484610191565b5060019392505050565b610183828261033b565b5050565b60003361016f8185855b6001600160a01b0383166101fa5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084015b60405180910390fd5b6001600160a01b03821661025c5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016101f1565b6001600160a01b0383166000908152602081905260409020548111156102d35760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016101f1565b6001600160a01b038381166000818152602081815260408083208054879003905593861680835291849020805486019055925184815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b6001600160a01b0382166103915760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016101f1565b80600260008282546103a391906104d1565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b80356001600160a01b038116811461041157600080fd5b919050565b6000806040838503121561042957600080fd5b610432836103fa565b946020939093013593505050565b60008060006060848603121561045557600080fd5b61045e846103fa565b925061046c602085016103fa565b9150604084013590509250925092565b60006020828403121561048e57600080fd5b610497826103fa565b9392505050565b600080604083850312156104b157600080fd5b6104ba836103fa565b91506104c8602084016103fa565b90509250929050565b8082018082111561015c57634e487b7160e01b600052601160045260246000fdfea264697066735822122020d7e8b980aa0c2b46b040d513e5ae1f916c9610cc2589a32d3485f141c4d93e64736f6c63430008180033", } // ContractERC20MockABI is the input ABI used to generate the binding from. diff --git a/contracts/lib/eigenlayer-middleware b/contracts/lib/eigenlayer-middleware index a1801f07e..1273f59e4 160000 --- a/contracts/lib/eigenlayer-middleware +++ b/contracts/lib/eigenlayer-middleware @@ -1 +1 @@ -Subproject commit a1801f07e15192ef06db86dfec716eb2b6a4fe90 +Subproject commit 1273f59e42c9c4b9be1c33623c4ad6b0771d594a diff --git a/core/chainio/avs_reader.go b/core/chainio/avs_reader.go index 78d46af78..60c42f137 100644 --- a/core/chainio/avs_reader.go +++ b/core/chainio/avs_reader.go @@ -48,10 +48,10 @@ func NewAvsReaderFromConfig(baseConfig *config.BaseConfig, ecdsaConfig *config.E } func (r *AvsReader) GetErc20Mock(tokenAddr gethcommon.Address) (*contractERC20Mock.ContractERC20Mock, error) { - erc20Mock, err := contractERC20Mock.NewContractERC20Mock(tokenAddr, r.AvsContractBindings.ethClient) + erc20Mock, err := contractERC20Mock.NewContractERC20Mock(tokenAddr, &r.AvsContractBindings.ethClient) if err != nil { // Retry with fallback client - erc20Mock, err = contractERC20Mock.NewContractERC20Mock(tokenAddr, r.AvsContractBindings.ethClientFallback) + erc20Mock, err = contractERC20Mock.NewContractERC20Mock(tokenAddr, &r.AvsContractBindings.ethClientFallback) if err != nil { r.logger.Error("Failed to fetch ERC20Mock contract", "err", err) } diff --git a/core/chainio/avs_writer.go b/core/chainio/avs_writer.go index f6c817358..a6a820195 100644 --- a/core/chainio/avs_writer.go +++ b/core/chainio/avs_writer.go @@ -23,8 +23,8 @@ type AvsWriter struct { AvsContractBindings *AvsServiceBindings logger logging.Logger Signer signer.Signer - Client eth.Client - ClientFallback eth.Client + Client eth.InstrumentedClient + ClientFallback eth.InstrumentedClient } func NewAvsWriterFromConfig(baseConfig *config.BaseConfig, ecdsaConfig *config.EcdsaConfig) (*AvsWriter, error) { @@ -119,7 +119,6 @@ func (w *AvsWriter) checkRespondToTaskFeeLimit(tx *types.Transaction, txOpts bin // Proceed to check values against simulated costs w.logger.Error("Failed to get batch state", "error", err) w.logger.Info("Proceeding with simulated cost checks") - return w.compareBalances(simulatedCost, aggregatorAddress, senderAddress) } } diff --git a/core/chainio/bindings.go b/core/chainio/bindings.go index 8aeb787d9..a0eb70478 100644 --- a/core/chainio/bindings.go +++ b/core/chainio/bindings.go @@ -12,19 +12,19 @@ import ( type AvsServiceBindings struct { ServiceManager *csservicemanager.ContractAlignedLayerServiceManager ServiceManagerFallback *csservicemanager.ContractAlignedLayerServiceManager - ethClient eth.Client - ethClientFallback eth.Client + ethClient eth.InstrumentedClient + ethClientFallback eth.InstrumentedClient logger logging.Logger } -func NewAvsServiceBindings(serviceManagerAddr, blsOperatorStateRetrieverAddr gethcommon.Address, ethClient eth.Client, ethClientFallback eth.Client, logger logging.Logger) (*AvsServiceBindings, error) { - contractServiceManager, err := csservicemanager.NewContractAlignedLayerServiceManager(serviceManagerAddr, ethClient) +func NewAvsServiceBindings(serviceManagerAddr, blsOperatorStateRetrieverAddr gethcommon.Address, ethClient eth.InstrumentedClient, ethClientFallback eth.InstrumentedClient, logger logging.Logger) (*AvsServiceBindings, error) { + contractServiceManager, err := csservicemanager.NewContractAlignedLayerServiceManager(serviceManagerAddr, ðClient) if err != nil { logger.Error("Failed to fetch AlignedLayerServiceManager contract", "err", err) return nil, err } - contractServiceManagerFallback, err := csservicemanager.NewContractAlignedLayerServiceManager(serviceManagerAddr, ethClientFallback) + contractServiceManagerFallback, err := csservicemanager.NewContractAlignedLayerServiceManager(serviceManagerAddr, ðClientFallback) if err != nil { logger.Error("Failed to fetch AlignedLayerServiceManager contract", "err", err) return nil, err diff --git a/core/config/base.go b/core/config/base.go index 65f639429..4eaef531b 100644 --- a/core/config/base.go +++ b/core/config/base.go @@ -9,7 +9,9 @@ import ( "github.com/Layr-Labs/eigensdk-go/chainio/clients/eth" sdklogging "github.com/Layr-Labs/eigensdk-go/logging" + rpccalls "github.com/Layr-Labs/eigensdk-go/metrics/collectors/rpc_calls" sdkutils "github.com/Layr-Labs/eigensdk-go/utils" + "github.com/prometheus/client_golang/prometheus" "github.com/urfave/cli/v2" ) @@ -27,10 +29,10 @@ type BaseConfig struct { Logger sdklogging.Logger EthRpcUrl string EthWsUrl string - EthRpcClient eth.Client - EthRpcClientFallback eth.Client - EthWsClient eth.Client - EthWsClientFallback eth.Client + EthRpcClient eth.InstrumentedClient + EthRpcClientFallback eth.InstrumentedClient + EthWsClient eth.InstrumentedClient + EthWsClientFallback eth.InstrumentedClient EigenMetricsIpPortAddress string ChainId *big.Int } @@ -96,12 +98,15 @@ func NewBaseConfig(configFilePath string) *BaseConfig { log.Fatal("Eth ws url or fallback is empty") } - ethWsClient, err := eth.NewClient(baseConfigFromYaml.EthWsUrl) + reg := prometheus.NewRegistry() + rpcCallsCollector := rpccalls.NewCollector("ethWs", reg) + ethWsClient, err := eth.NewInstrumentedClient(baseConfigFromYaml.EthWsUrl, rpcCallsCollector) if err != nil { log.Fatal("Error initializing eth ws client: ", err) } - - ethWsClientFallback, err := eth.NewClient(baseConfigFromYaml.EthWsUrlFallback) + reg = prometheus.NewRegistry() + rpcCallsCollector = rpccalls.NewCollector("ethWsFallback", reg) + ethWsClientFallback, err := eth.NewInstrumentedClient(baseConfigFromYaml.EthWsUrlFallback, rpcCallsCollector) if err != nil { log.Fatal("Error initializing eth ws client fallback: ", err) } @@ -110,12 +115,16 @@ func NewBaseConfig(configFilePath string) *BaseConfig { log.Fatal("Eth rpc url is empty") } - ethRpcClient, err := eth.NewClient(baseConfigFromYaml.EthRpcUrl) + reg = prometheus.NewRegistry() + rpcCallsCollector = rpccalls.NewCollector("ethRpc", reg) + ethRpcClient, err := eth.NewInstrumentedClient(baseConfigFromYaml.EthRpcUrl, rpcCallsCollector) if err != nil { log.Fatal("Error initializing eth rpc client: ", err) } - ethRpcClientFallback, err := eth.NewClient(baseConfigFromYaml.EthRpcUrlFallback) + reg = prometheus.NewRegistry() + rpcCallsCollector = rpccalls.NewCollector("ethRpc", reg) + ethRpcClientFallback, err := eth.NewInstrumentedClient(baseConfigFromYaml.EthRpcUrlFallback, rpcCallsCollector) if err != nil { log.Fatal("Error initializing eth rpc client fallback: ", err) } @@ -136,10 +145,10 @@ func NewBaseConfig(configFilePath string) *BaseConfig { Logger: logger, EthRpcUrl: baseConfigFromYaml.EthRpcUrl, EthWsUrl: baseConfigFromYaml.EthWsUrl, - EthRpcClient: ethRpcClient, - EthRpcClientFallback: ethRpcClientFallback, - EthWsClient: ethWsClient, - EthWsClientFallback: ethWsClientFallback, + EthRpcClient: *ethRpcClient, + EthRpcClientFallback: *ethRpcClientFallback, + EthWsClient: *ethWsClient, + EthWsClientFallback: *ethWsClientFallback, EigenMetricsIpPortAddress: baseConfigFromYaml.EigenMetricsIpPortAddress, ChainId: chainId, } diff --git a/core/utils/eth_client_utils.go b/core/utils/eth_client_utils.go index 25ae91776..afa26b867 100644 --- a/core/utils/eth_client_utils.go +++ b/core/utils/eth_client_utils.go @@ -15,7 +15,7 @@ import ( const maxRetries = 25 const sleepTime = 5 * time.Second -func WaitForTransactionReceipt(client eth.Client, ctx context.Context, txHash gethcommon.Hash) (*types.Receipt, error) { +func WaitForTransactionReceipt(client eth.InstrumentedClient, ctx context.Context, txHash gethcommon.Hash) (*types.Receipt, error) { for i := 0; i < maxRetries; i++ { receipt, err := client.TransactionReceipt(ctx, txHash) if err != nil { diff --git a/docs/1_introduction/0_about_aligned.md b/docs/1_introduction/0_about_aligned.md index 6a0bef2bf..9e5b58b21 100644 --- a/docs/1_introduction/0_about_aligned.md +++ b/docs/1_introduction/0_about_aligned.md @@ -90,3 +90,7 @@ Since Aligned’s operators only need to run the verification code on bare metal - Adding new proof systems is straightforward. Preliminary numbers show that Aligned can verify more than 1000 proofs per second, over two orders of magnitude than the EVM at nominal capacity. Using effective batching techniques, we can split the task creation and verification cost between thousands of proofs. + +## Future additions + +- Propagation of the results to different L2s diff --git a/docs/1_introduction/1_getting_started.md b/docs/1_introduction/1_getting_started.md index 864153ab0..21cfa1a02 100644 --- a/docs/1_introduction/1_getting_started.md +++ b/docs/1_introduction/1_getting_started.md @@ -30,9 +30,8 @@ aligned submit \ --vm_program ~/.aligned/test_files/sp1_fibonacci.elf \ --aligned_verification_data_path ~/.aligned/aligned_verification_data \ --batcher_url wss://batcher.alignedlayer.com \ ---chain holesky \ ---rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 +--network holesky \ +--rpc_url https://ethereum-holesky-rpc.publicnode.com ``` 5. You should get a response like this: @@ -53,8 +52,7 @@ Use the link in the response to check the status of your transaction in the Alig aligned verify-proof-onchain \ --aligned-verification-data ~/.aligned/aligned_verification_data/*.json \ --rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---chain holesky \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 +--network holesky ``` This is reading the result of the proof verification in Ethereum. diff --git a/docs/1_introduction/4_faq.md b/docs/1_introduction/4_faq.md index 28607991f..fec8f4a10 100644 --- a/docs/1_introduction/4_faq.md +++ b/docs/1_introduction/4_faq.md @@ -6,6 +6,27 @@ Aligned’s mission is to extend Ethereum’s zero-knowledge capabilities. We ar The question we want to share is: If we are sure that zero-knowledge proofs are the future of Ethereum, but we don't know which of the many possible zero-knowledge futures will win, **then how do we build infrastructure for Ethereum to make it compatible with any future zero-knowledge proving system?** +### What are the security guarantees and trust assumptions of Aligned? + +Aligned verifies proofs by having the operators re-execute the verification code for each proof and, if all of the proofs are valid, each of them signs a message containing a commitment to the proof and public input or the root of the batch. The aggregator is responsible for receiving the signatures, checking the quorum, performing the aggregation and sending them to Ethereum. + +- 67% of the operators behaving dishonestly to be able to submit false proofs. +- 33% of the operators colluding to censor a batch of proofs or task. However, in the case of a batch, the operators can only censor the whole batch, but not a particular proof included in it. +- The aggregator can censor batches or proofs by not sending the aggregated signature. + +### What is the batcher? + +We have a service called the batcher that batches enough proofs to send to the AVS in Eigen Layer to reduce on-chain verification costs. Users can submit their proofs to Aligned directly without the batcher. The batcher is fully optional. The batcher is an optimization to reduce on-chain verification costs. + +### What are the security guarantees added by the batcher? + +A batcher can censor proofs. The user can run their own batcher to avoid censorship or can send a task to verify proofs in Aligned via Ethereum without using the batcher. +The batcher cannot transfer user's funds to other accounts, only spend them to create verification tasks and pay to the aggregator. We recommend to only deposit enough funds for a few months of operations. + +### How do I send proofs without a batcher? + +### How do I run my own batcher? + ### Why build Aligned on top of Ethereum? Ethereum is the most decentralized and most significant source of liquidity in the crypto ecosystem. We believe it is the most ambitious and long-term project on the internet. Aligned is being built to help Ethereum achieve its highest potential, and we believe this is only possible through validity/zero-knowledge proofs. diff --git a/docs/2_architecture/0_supported_verifiers.md b/docs/2_architecture/0_supported_verifiers.md index 0ff137ac4..fa88ed876 100644 --- a/docs/2_architecture/0_supported_verifiers.md +++ b/docs/2_architecture/0_supported_verifiers.md @@ -4,14 +4,15 @@ Aligned's support for multiple proof systems is a significant advantage, as it a The following is the list of the verifiers currently supported by Aligned: -- :white_check_mark: gnark [(v0.11.0)](https://github.com/Consensys/gnark/releases/tag/v0.11.0) - Groth16 (with BN254) -- :white_check_mark: gnark [(v0.11.0)](https://github.com/Consensys/gnark/releases/tag/v0.11.0) - Plonk (with BN254 and BLS12-381) +- :white_check_mark: gnark - Groth16 (with BN254) [(v0.10.0)](https://github.com/Consensys/gnark/releases/tag/v0.10.0) +- :white_check_mark: gnark - Plonk (with BN254 and BLS12-381) [(v0.10.0)](https://github.com/Consensys/gnark/releases/tag/v0.10.0) - :white_check_mark: SP1 [(v1.0.1)](https://github.com/succinctlabs/sp1/releases/tag/v1.0.1) - :white_check_mark: Risc0 [(v1.0.1)](https://github.com/risc0/risc0/releases/tag/v1.0.1) +- 🏗️ Circom +- 🏗️ Lambdaworks +- 🏗️ Kimchi -The following are going to be added soon: +The following are in the roadmap to be added: -- :black_square_button: Kimchi - :black_square_button: Jolt - :black_square_button: Nexus -- :black_square_button: Circom diff --git a/docs/3_guides/0_submitting_proofs.md b/docs/3_guides/0_submitting_proofs.md index e1dc33a07..1f30a44b5 100644 --- a/docs/3_guides/0_submitting_proofs.md +++ b/docs/3_guides/0_submitting_proofs.md @@ -8,8 +8,8 @@ If you run the examples below, make sure you are in Aligned's repository root. The following is the list of the verifiers currently supported by Aligned: -- :white_check_mark: gnark [(v0.11.0)](https://github.com/Consensys/gnark/releases/tag/v0.11.0) - Groth16 (with BN254) -- :white_check_mark: gnark [(v0.11.0)](https://github.com/Consensys/gnark/releases/tag/v0.11.0) - Plonk (with BN254 and BLS12-381) +- :white_check_mark: gnark - Groth16 (with BN254) +- :white_check_mark: gnark - Plonk (with BN254 and BLS12-381) - :white_check_mark: SP1 [(v1.0.1)](https://github.com/succinctlabs/sp1/releases/tag/v1.0.1) - :white_check_mark: Risc0 [(v1.0.1)](https://github.com/risc0/risc0/releases/tag/v1.0.1) @@ -25,28 +25,28 @@ You need to have installed [Foundry](https://book.getfoundry.sh/getting-started/ - If you are creating a new account, create a private key with: - ```bash - cast wallet new-mnemonic --words 12 - ``` + ```bash + cast wallet new-mnemonic --words 12 + ``` - It will show you a new mnemonic phrase and a public-private key pair, similar to the following example: + It will show you a new mnemonic phrase and a public-private key pair, similar to the following example: - ``` - Phrase: - test test test test test test test test test test test test + ``` + Phrase: + test test test test test test test test test test test test - Accounts: - - Account 0: - Address: 0xabcd...1234 - Private key: 0x1234...abcd - ``` + Accounts: + - Account 0: + Address: 0xabcd...1234 + Private key: 0x1234...abcd + ``` - Import the wallet using the private key previously generated, or whichever you want to use, and write a password to use it. - ```bash - mkdir -p ~/.aligned_keystore/ - cast wallet import ~/.aligned_keystore/keystore0 --interactive - ``` + ```bash + mkdir -p ~/.aligned_keystore/ + cast wallet import ~/.aligned_keystore/keystore0 --interactive + ``` You have to paste your private key and set a password for the keystore file. @@ -63,10 +63,9 @@ To be able to send proofs to Aligned using the Batcher, the user must fund its t To use it, you can use the `aligned` CLI, as shown with the following example: ```bash -aligned deposit-to-batcher \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 \ +aligned deposit-to-batcher \ --rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---chain holesky \ +--network holesky \ --keystore_path \ --amount 0.1ether ``` @@ -75,7 +74,7 @@ These commands allow the usage of the following flags: - `--payment_service_addr` to specify the address of the Batcher Payment Service smart contract. - `--rpc_url` to specify the rpc url to be used. -- `--chain` to specify the chain id to be used. Could be holesky or devnet. +- `--network` to specify the chain id to be used. Could be holesky or devnet. - `--keystore_path` the path to the keystore. - `--amount` the number of ethers to transfer to the Batcher. - Note: `--amount` flag parameter must be with the shown format. The amount followed by the `ether` keyword to specify how many ethers you wish to deposit to the Batcher. @@ -83,8 +82,7 @@ These commands allow the usage of the following flags: After depositing funds, you can verify the Service has correctly received them by executing the following command: ```bash -aligned get-user-balance \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 \ +aligned get-user-balance \ --rpc_url https://ethereum-holesky-rpc.publicnode.com \ --user_addr ``` @@ -101,16 +99,16 @@ This guide will focus on how to submit proofs using the Aligned CLI. To integrat Proof submission is done via the `submit` command of the Aligned CLI. The arguments for the submit command are: -- `proving_system`: The proving system corresponding to the proof you want to submit. -- `proof`: The path of the proof associated to the computation to be verified. -- `vm_program`: When the proving system involves the execution of a program in a zkVM, this argument is associated with the compiled program or some other identifier of the program. -- `pub_input`: The path to the file with the public input associated with the proof. -- `batcher_url`: The batcher websocket URL. -- `chain` to specify the chain id to be used. Could be holesky or devnet. -- `rpc_url`: The RPC Ethereum node URL. -- `payment_service_addr`: The Ethereum address of the Batcher Payments System contract. -- `proof_generator_addr`: An optional parameter that can be used in some applications to avoid front-running. -- `batch_inclusion_data_directory_path`: An optional parameter indicating the directory where to store the batcher response data. If not provided, the folder with the responses will be created in the current directory. +* `proving_system`: The proving system corresponding to the proof you want to submit. +* `proof`: The path of the proof associated to the computation to be verified. +* `vm_program`: When the proving system involves the execution of a program in a zkVM, this argument is associated with the compiled program or some other identifier of the program. +* `pub_input`: The path to the file with the public input associated with the proof. +* `batcher_url`: The batcher websocket URL. +* `chain` to specify the chain id to be used. Could be holesky or devnet. +* `rpc_url`: The RPC Ethereum node URL. +* `payment_service_addr`: The Ethereum address of the Batcher Payments System contract. +* `proof_generator_addr`: An optional parameter that can be used in some applications to avoid front-running. +* `batch_inclusion_data_directory_path`: An optional parameter indicating the directory where to store the batcher response data. If not provided, the folder with the responses will be created in the current directory. ### SP1 proof @@ -128,9 +126,8 @@ aligned submit \ --proof_generator_addr [proof_generator_addr] \ --batch_inclusion_data_directory_path [batch_inclusion_data_directory_path] \ --keystore_path \ ---chain holesky \ ---rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 +--network holesky \ +--rpc_url https://ethereum-holesky-rpc.publicnode.com ``` **Example** @@ -143,9 +140,8 @@ aligned submit \ --vm_program ./scripts/test_files/sp1/sp1_fibonacci.elf \ --batcher_url wss://batcher.alignedlayer.com \ --keystore_path ~/.aligned_keystore/keystore0 \ ---chain holesky \ ---rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 +--network holesky \ +--rpc_url https://ethereum-holesky-rpc.publicnode.com ``` ### Risc0 proof @@ -165,9 +161,18 @@ aligned submit \ --proof_generator_addr [proof_generator_addr] \ --batch_inclusion_data_directory_path [batch_inclusion_data_directory_path] \ --keystore_path \ ---chain holesky \ ---rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 +--network holesky \ +--rpc_url https://ethereum-holesky-rpc.publicnode.com +``` + +**NOTE**: As said above, Aligned currently supports Risc0 proofs from `risc0-zkvm` version `v1.0.1`. For generating proofs using `cargo risc-zero` please ensure you are using `v1.0.1` or your proof will not be verified. + +If you can't install `cargo-risczero` `v1.0.1`, you can manually modify your `cargo.toml` on the host project to point to `v1.0.1`: + +```toml +risc0-zkvm = { git = "https://github.com/risc0/risc0", tag = "v1.0.1", default-features = false, features = [ + "prove", +] } ``` **Example** @@ -182,9 +187,8 @@ aligned submit \ --batcher_url wss://batcher.alignedlayer.com \ --aligned_verification_data_path ~/.aligned/aligned_verification_data \ --keystore_path ~/.aligned_keystore/keystore0 \ ---chain holesky \ ---rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 +--network holesky \ +--rpc_url https://ethereum-holesky-rpc.publicnode.com ``` ### GnarkPlonkBn254, GnarkPlonkBls12_381 and Groth16Bn254 @@ -202,9 +206,8 @@ aligned submit \ --proof_generator_addr [proof_generator_addr] \ --batch_inclusion_data_directory_path [batch_inclusion_data_directory_path] \ --keystore_path \ ---chain holesky \ ---rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 +--network holesky \ +--rpc_url https://ethereum-holesky-rpc.publicnode.com ``` **Examples**: @@ -218,9 +221,8 @@ aligned submit \ --vk ./scripts/test_files/gnark_plonk_bn254_script/plonk.vk \ --batcher_url wss://batcher.alignedlayer.com \ --keystore_path ~/.aligned_keystore/keystore0 \ ---chain holesky \ ---rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 +--network holesky \ +--rpc_url https://ethereum-holesky-rpc.publicnode.com ``` ```bash @@ -232,9 +234,8 @@ aligned submit \ --vk ./scripts/test_files/gnark_plonk_bls12_381_script/plonk.vk \ --batcher_url wss://batcher.alignedlayer.com \ --keystore_path ~/.aligned_keystore/keystore0 \ ---chain holesky \ ---rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 +--network holesky \ +--rpc_url https://ethereum-holesky-rpc.publicnode.com ``` ```bash @@ -246,7 +247,6 @@ aligned submit \ --vk ./scripts/test_files/gnark_groth16_bn254_infinite_script/infinite_proofs/ineq_1_groth16.vk \ --batcher_url wss://batcher.alignedlayer.com \ --keystore_path ~/.aligned_keystore/keystore0 \ ---chain holesky \ ---rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 +--network holesky \ +--rpc_url https://ethereum-holesky-rpc.publicnode.com ``` diff --git a/docs/3_guides/1.2_SDK_api_reference.md b/docs/3_guides/1.2_SDK_api_reference.md index 56da68f75..9df3507a7 100644 --- a/docs/3_guides/1.2_SDK_api_reference.md +++ b/docs/3_guides/1.2_SDK_api_reference.md @@ -302,3 +302,82 @@ wallet = wallet.with_chain_id(chain_id); - `EthereumProviderError` if there is an error in the connection with the RPC provider. - `EthereumCallError` if there is an error in the Ethereum call. + +## `estimate_fee` + +Estimates the fee the user would have to pay for submitting a proof to Aligned. Depending on the +priority the user wants to have in the batch, the `estimate` parameter can be set. + +```rust +pub async fn estimate_fee( + eth_rpc_url: &str, + estimate: PriceEstimate, +) -> Result +``` + +### Arguments + +- `eth_rpc_url` - The URL of the Ethereum RPC node. +- `estimate` - The parameter to set the priority for the proof to be included in the batch. It can be one + of `Min`, `Default` or `Max`. + +#### Returns + +- `Result` - the estimated `max_fee` depending on the batch inclusion preference of the user. + +#### Errors + +- `EthereumProviderError` if there is an error in the connection with the RPC provider. +- `EthereumCallError` if there is an error in the Ethereum call. + +## `compute_max_fee` + +Computes `max_fee` for a proof based on the number of proofs in a batch (`num_proofs_per_batch`) and number of proofs (`num_proofs`) in that batch the user would pay for i.e (`num_proofs` / `num_proofs_per_batch`). + +```rust +pub async fn compute_max_fee( + eth_rpc_url: &str, + num_proofs: usize, + num_proofs_per_batch: usize, +) -> Result +``` + +### Arguments + +- `eth_rpc_url` - The URL of the Ethereum RPC node. +- `num_proofs` - The number of proofs in a batch the user would pay for. +- `num_proofs_per_batch` - The number of proofs within a batch. + +#### Returns + +- `Result` - The calculated `max_fee` as a `U256`. + +#### Errors + +- `EthereumProviderError` if there is an error in the connection with the RPC provider. +- `EthereumCallError` if there is an error in the Ethereum call. + +## `fee_per_proof` + +Returns the `fee_per_proof` based on the current gas price for a batch compromised of `num_proofs_per_batch` i.e. (1 / `num_proofs_per_batch`). + +```rust +pub async fn fee_per_proof( + eth_rpc_url: &str, + num_proofs_per_batch: usize, +) -> Result +``` + +### Arguments + +- `eth_rpc_url` - The URL of the users Ethereum RPC node. +- `num_proofs_per_batch` - The number of proofs within a batch. + +#### Returns + +- `Result` - The fee per proof of a batch of `num_proofs_per_batch` proofs as a `U256`. + +#### Errors + +- `EthereumProviderError` if there is an error in the connection with the RPC provider. +- `EthereumCallError` if there is an error in the Ethereum call. diff --git a/docs/3_guides/1_SDK_how_to.md b/docs/3_guides/1_SDK_how_to.md index f03c2e422..203005e99 100644 --- a/docs/3_guides/1_SDK_how_to.md +++ b/docs/3_guides/1_SDK_how_to.md @@ -23,8 +23,8 @@ version of the release that has the `latest` badge. To get the SDK up and running in your project, you must first import it ```rust -use aligned_sdk::core::types::{AlignedVerificationData, Network, ProvingSystemId, VerificationData}; -use aligned_sdk::sdk::{submit_and_wait, get_next_nonce}; +use aligned_sdk::core::types::{PriceEstimate, AlignedVerificationData, Network, ProvingSystemId, VerificationData}; +use aligned_sdk::sdk::{estimate_fee, submit_and_wait, get_next_nonce}; ``` And then you can do a simple call of, for example, `get_next_nonce` @@ -67,7 +67,7 @@ fn main() { let wallet = LocalWallet::decrypt_keystore(args.keystore_path, &keystore_password) .expect("Failed to decrypt keystore") .with_chain_id(17000u64); - let max_fee: U256 = 10000000000000000; //0.01 ETH + let max_fee: U256 = estimate_fee(&rpc_url, PriceEstimate::Default).await.unwrap(); // Call to SDK: match submit_and_wait_verification( diff --git a/docs/3_guides/3.2_generate_gnark_proof.md b/docs/3_guides/3.2_generate_gnark_proof.md index 783fdf828..f53b89598 100644 --- a/docs/3_guides/3.2_generate_gnark_proof.md +++ b/docs/3_guides/3.2_generate_gnark_proof.md @@ -6,57 +6,56 @@ - 2 Initialize a Go Module: Create a new directory for your project and initialize a Go module -```bash= -mkdir gnark_plonk_circuit -cd gnark_plonk_circuit -go mod init gnark_plonk_circuit -``` + ```bash= + mkdir gnark_plonk_circuit + cd gnark_plonk_circuit + go mod init gnark_plonk_circuit + ``` - 3 Install Gnark: Add the library to your project -```bash= -go get github.com/consensys/gnark@v0.11.0 -go get github.com/consensys/gnark-crypto@v0.14.0 -``` + ```bash= + go get github.com/consensys/gnark@v0.10.0 + ``` ## Step 2: Import dependencies -```bash= -import ( - "fmt" - "log" - "os" - "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark/backend/plonk" - cs "github.com/consensys/gnark/constraint/bn254" - "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/test/unsafekzg" - "github.com/consensys/gnark/frontend/cs/scs" -) -``` + ```bash= + import ( + "fmt" + "log" + "os" + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark/backend/plonk" + cs "github.com/consensys/gnark/constraint/bn254" + "github.com/consensys/gnark/frontend" + "github.com/consensys/gnark/test/unsafekzg" + "github.com/consensys/gnark/frontend/cs/scs" + ) + ``` Here's what each package is used for: -`fmt`: Standard Go library for formatted input/output. +```fmt```: Standard Go library for formatted input/output. -`log`: Standard Go library for event logging. +```log```: Standard Go library for event logging. -`os`: Standard Go library for interacting with the operating system. +```os```: Standard Go library for interacting with the operating system. -`path/filepath`: Standard Go library for portable file path manipulation. +```path/filepath```: Standard Go library for portable file path manipulation. -`github.com/consensys/gnark-crypto/ecc`: Provides cryptographic operations over elliptic curves. +```github.com/consensys/gnark-crypto/ecc```: Provides cryptographic operations over elliptic curves. -`github.com/consensys/gnark/backend/plonk` Gnark backend for the PLONK proving system. +```github.com/consensys/gnark/backend/plonk``` Gnark backend for the PLONK proving system. -`github.com/consensys/gnark/constraint/bn254`: Provides types and functions to work with constraint systems +```github.com/consensys/gnark/constraint/bn254```: Provides types and functions to work with constraint systems specifically for the BN254 curve. -`github.com/consensys/gnark/frontend`: Provides the API for defining constraints and creating witness data. +```github.com/consensys/gnark/frontend```: Provides the API for defining constraints and creating witness data. -`github.com/consensys/gnark/test/unsafekzg`: Gnark testing utilities for KZG commitments. +```github.com/consensys/gnark/test/unsafekzg```: Gnark testing utilities for KZG commitments. -`github.com/consensys/gnark/frontend/cs/scs`: Gnark frontend for the SCS (Sparse Constraint System) builder. +```github.com/consensys/gnark/frontend/cs/scs```: Gnark frontend for the SCS (Sparse Constraint System) builder. ## Step 3: Define the circuit @@ -64,22 +63,22 @@ The circuit structure is defined in this case using the equation $x^3 + x + 5 = y$ -```bash= -// CubicCircuit defines a simple circuit -// x**3 + x + 5 == y -type CubicCircuit struct { - X frontend.Variable `gnark:"x"` - Y frontend.Variable `gnark:",public"` -} -``` + ```bash= + // CubicCircuit defines a simple circuit + // x**3 + x + 5 == y + type CubicCircuit struct { + X frontend.Variable `gnark:"x"` + Y frontend.Variable `gnark:",public"` + } + ``` Here -`CubicCircuit`struct contains the variables `X` and `Y` +```CubicCircuit```struct contains the variables ```X``` and ```Y``` -`X` is a secret input, annotated as `'gnark:"x"'` +```X``` is a secret input, annotated as ```'gnark:"x"'``` -`Y` is a public input, annotated as `'gnark:",public"'` +```Y``` is a public input, annotated as ```'gnark:",public"'``` ## Step 4: Define the circuit constraints: @@ -87,23 +86,23 @@ Establish constraints that the circuit must satisfy. Here you define the logic that relates inputs to outputs, encapsulating the computation: -```bash= -// Define declares the circuit constraints -// x**3 + x + 5 == y -func (circuit *CubicCircuit) Define(api frontend.API) error { - x3 := api.Mul(circuit.X, circuit.X, circuit.X) - api.AssertIsEqual(circuit.Y, api.Add(x3, circuit.X, 5)) - return nil -} -``` + ```bash= + // Define declares the circuit constraints + // x**3 + x + 5 == y + func (circuit *CubicCircuit) Define(api frontend.API) error { + x3 := api.Mul(circuit.X, circuit.X, circuit.X) + api.AssertIsEqual(circuit.Y, api.Add(x3, circuit.X, 5)) + return nil + } + ``` -The `Define` method specifies the constraints for the circuit. +The ```Define``` method specifies the constraints for the circuit. -`x3 := api.Mul(circuit.X, circuit.X, circuit.X)` computes X\*\*3 +```x3 := api.Mul(circuit.X, circuit.X, circuit.X)``` computes X**3 -`api.AssertIsEqual(circuit.Y, api.Add(x3, circuit.X, 5)` asserts that X\*\*3 + X + 5 == Y +```api.AssertIsEqual(circuit.Y, api.Add(x3, circuit.X, 5)``` asserts that X**3 + X + 5 == Y -There are other options that we might use like `ÀssertDifferent` `AssertIsLessOrEqual` +There are other options that we might use like ```ÀssertDifferent``` ```AssertIsLessOrEqual``` ## Step 5: Compile the circuit and generate the proof @@ -111,138 +110,138 @@ Detail the steps to compile the circuit, generate a witness, create a proof, and we need to specify the directory where the proof, verification key and the public key will be saved -```bash -outputDir := "gnark_plonk_circuit/" -``` + ```bash + outputDir := "gnark_plonk_circuit/" + ``` To compile the circuit, we do -```bash= - var circuit CubicCircuit - // Compile the circuit using scs.NewBuilder - ccs, err := frontend.Compile(ecc.BN254.ScalarField(), scs.NewBuilder, &circuit) - if err != nil { - panic("circuit compilation error") - } -``` + ```bash= + var circuit CubicCircuit + // Compile the circuit using scs.NewBuilder + ccs, err := frontend.Compile(ecc.BN254.ScalarField(), scs.NewBuilder, &circuit) + if err != nil { + panic("circuit compilation error") + } + ``` where -The `frontend.Compile` function compiles the circuit using the SCS +The ```frontend.Compile``` function compiles the circuit using the SCS constraint system. -`ecc.BN254.ScalarField()` specifies the scalar field, in this case for the BN254 curve. +```ecc.BN254.ScalarField()``` specifies the scalar field, in this case for the BN254 curve. -`scs.NewBuilder` is used to build the sparse constraint system. +```scs.NewBuilder``` is used to build the sparse constraint system. We generate the SRS (Structured Reference String) -```bash= - // Generate the SRS and its Lagrange interpolation - r1cs := ccs.(*cs.SparseR1CS) - srs, srsLagrangeInterpolation, err := unsafekzg.NewSRS(r1cs) - if err != nil { - panic("KZG setup error") - } -``` + ```bash= + // Generate the SRS and its Lagrange interpolation + r1cs := ccs.(*cs.SparseR1CS) + srs, srsLagrangeInterpolation, err := unsafekzg.NewSRS(r1cs) + if err != nil { + panic("KZG setup error") + } + ``` -`r1cs := ccs.(*cs.SparseR1CS)` converts the compiled circuit to a sparse R1CS(Rank-1 Constraint Systems) format +```r1cs := ccs.(*cs.SparseR1CS)``` converts the compiled circuit to a sparse R1CS(Rank-1 Constraint Systems) format required by the SRS generation. -`unsafekzg.NewSRS` generates the structured reference string (SRS) and its Lagrange interpolation. +```unsafekzg.NewSRS``` generates the structured reference string (SRS) and its Lagrange interpolation. Next, we need to set up PLONK -```bash= -pk, vk, _ := plonk.Setup(ccs, srs, srsLagrangeInterpolation) -``` + ```bash= + pk, vk, _ := plonk.Setup(ccs, srs, srsLagrangeInterpolation) + ``` -`plonk.Setup` initializes the PLONK proving system with the constraint system, SRS, and its Lagrange interpolation. -This generates the proving key `pk` and verification key `vk` +```plonk.Setup``` initializes the PLONK proving system with the constraint system, SRS, and its Lagrange interpolation. +This generates the proving key ```pk``` and verification key ```vk``` Then the Witness is created -```bash= - assignment := CubicCircuit{X: 3, Y: 35} - fullWitness, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) - if err != nil { - log.Fatal(err) - } - publicWitness, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField(), frontend.PublicOnly()) - if err != nil { - log.Fatal(err) - } -``` + ```bash= + assignment := CubicCircuit{X: 3, Y: 35} + fullWitness, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) + if err != nil { + log.Fatal(err) + } + publicWitness, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField(), frontend.PublicOnly()) + if err != nil { + log.Fatal(err) + } + ``` -An assignment to the circuit variables is created: `X = 3` and `Y = 35`. +An assignment to the circuit variables is created: ```X = 3``` and ```Y = 35```. -`frontend.NewWitness` creates the full witness including all variables. +```frontend.NewWitness``` creates the full witness including all variables. -`frontend.NewWitness` with `frontend.PublicOnly()` creates the public witness including only the public +```frontend.NewWitness``` with ```frontend.PublicOnly()``` creates the public witness including only the public variables. Generate the Proof: -```bash= -proof, err := plonk.Prove(ccs, pk, fullWitness) - if err != nil { - panic("PLONK proof generation error") - } -``` + ```bash= + proof, err := plonk.Prove(ccs, pk, fullWitness) + if err != nil { + panic("PLONK proof generation error") + } + ``` -`plonk.Prove` generates a proof using the compiled circuit, proving key and full witness +```plonk.Prove``` generates a proof using the compiled circuit, proving key and full witness Then to Verify -```bash= - // Verify the proof - err = plonk.Verify(proof, vk, publicWitness) - if err != nil { - panic("PLONK proof not verified") - } -``` + ```bash= + // Verify the proof + err = plonk.Verify(proof, vk, publicWitness) + if err != nil { + panic("PLONK proof not verified") + } + ``` -`plonk.Verify` verifies the proof using the compiled circuit, proving key and full witness +```plonk.Verify``` verifies the proof using the compiled circuit, proving key and full witness Finally, we have to serialize and save outputs -```bash= - // Open files for writing the proof, the verification key, and the public witness - proofFile, err := os.Create(outputDir + "plonk.proof") - if err != nil { - panic(err) - } - vkFile, err := os.Create( "plonk.vk") - if err != nil { - panic(err) - } - witnessFile, err := os.Create( "plonk_pub_input.pub") - if err != nil { - panic(err) - } - defer proofFile.Close() - defer vkFile.Close() - defer witnessFile.Close() - // Write the proof to the file - _, err = proof.WriteTo(proofFile) - if err != nil { - panic("could not serialize proof into file") - } - // Write the verification key to the file - _, err = vk.WriteTo(vkFile) - if err != nil { - panic("could not serialize verification key into file") - } - // Write the public witness to the file - _, err = publicWitness.WriteTo(witnessFile) - if err != nil { - panic("could not serialize proof into file") - } - fmt.Println("Proof written into plonk.proof") - fmt.Println("Verification key written into plonk.vk") - fmt.Println("Public witness written into plonk_pub_input.pub") -} -``` + ```bash= + // Open files for writing the proof, the verification key, and the public witness + proofFile, err := os.Create(outputDir + "plonk.proof") + if err != nil { + panic(err) + } + vkFile, err := os.Create( "plonk.vk") + if err != nil { + panic(err) + } + witnessFile, err := os.Create( "plonk_pub_input.pub") + if err != nil { + panic(err) + } + defer proofFile.Close() + defer vkFile.Close() + defer witnessFile.Close() + // Write the proof to the file + _, err = proof.WriteTo(proofFile) + if err != nil { + panic("could not serialize proof into file") + } + // Write the verification key to the file + _, err = vk.WriteTo(vkFile) + if err != nil { + panic("could not serialize verification key into file") + } + // Write the public witness to the file + _, err = publicWitness.WriteTo(witnessFile) + if err != nil { + panic("could not serialize proof into file") + } + fmt.Println("Proof written into plonk.proof") + fmt.Println("Verification key written into plonk.vk") + fmt.Println("Public witness written into plonk_pub_input.pub") + } + ``` Files are created for the proof, verification key, and public witness. @@ -252,102 +251,102 @@ This ensures that the proof and related data are saved for later use or verifica The complete code is: -```bash= -package main -import ( - "fmt" - "log" - "os" - "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark/backend/plonk" - cs "github.com/consensys/gnark/constraint/bn254" - "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/test/unsafekzg" - "github.com/consensys/gnark/frontend/cs/scs" -) -// CubicCircuit defines a simple circuit -// x**3 + x + 5 == y -type CubicCircuit struct { - // struct tags on a variable is optional - // default uses variable name and secret visibility. - X frontend.Variable `gnark:"x"` - Y frontend.Variable `gnark:",public"` -} -// Define declares the circuit constraints -// x**3 + x + 5 == y -func (circuit *CubicCircuit) Define(api frontend.API) error { - x3 := api.Mul(circuit.X, circuit.X, circuit.X) - api.AssertIsEqual(circuit.Y, api.Add(x3, circuit.X, 5)) - return nil -} -func main() { - var circuit CubicCircuit - // use scs.NewBuilder instead of r1cs.NewBuilder (groth16) - ccs, err := frontend.Compile(ecc.BN254.ScalarField(), scs.NewBuilder, &circuit) - if err != nil { - panic("circuit compilation error") - } - // use unsafekzg.NewSRS to generate the SRS and the Lagrange interpolation of the SRS - // Setup prepares the public data associated to a circuit + public inputs. - // The kzg SRS must be provided in canonical and lagrange form. - // For test purposes, see test/unsafekzg package. With an existing SRS generated through MPC in canonical form, - r1cs := ccs.(*cs.SparseR1CS) - srs, srsLagrangeInterpolation, err := unsafekzg.NewSRS(r1cs) - // srs, err := test.NewKZGSRS(r1cs) - if err != nil { - panic("KZG setup error") - } - // add srsLagrangeInterpolation to the Setup function - pk, vk, _ := plonk.Setup(ccs, srs, srsLagrangeInterpolation) - assignment := CubicCircuit{X: 3, Y: 35} - fullWitness, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) - if err != nil { - log.Fatal(err) - } - publicWitness, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField(), frontend.PublicOnly()) - if err != nil { - log.Fatal(err) - } - // This proof should be serialized for testing in the operator - proof, err := plonk.Prove(ccs, pk, fullWitness) - if err != nil { - panic("PLONK proof generation error") - } - // The proof is verified before writing it into a file to make sure it is valid. - err = plonk.Verify(proof, vk, publicWitness) - if err != nil { - panic("PLONK proof not verified") - } - // Open files for writing the proof, the verification key and the public witness - proofFile, err := os.Create("plonk.proof") - if err != nil { - panic(err) - } - vkFile, err := os.Create("plonk.vk") - if err != nil { - panic(err) - } - witnessFile, err := os.Create( "plonk_pub_input.pub") - if err != nil { - panic(err) - } - defer proofFile.Close() - defer vkFile.Close() - defer witnessFile.Close() - _, err = proof.WriteTo(proofFile) - if err != nil { - panic("could not serialize proof into file") - } - _, err = vk.WriteTo(vkFile) - if err != nil { - panic("could not serialize verification key into file") - } - _, err = publicWitness.WriteTo(witnessFile) - if err != nil { - panic("could not serialize proof into file") - } - fmt.Println("Proof written into plonk.proof") - fmt.Println("Verification key written into plonk.vk") - fmt.Println("Public witness written into plonk_pub_input.pub") -} -``` + ```bash= + package main + import ( + "fmt" + "log" + "os" + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark/backend/plonk" + cs "github.com/consensys/gnark/constraint/bn254" + "github.com/consensys/gnark/frontend" + "github.com/consensys/gnark/test/unsafekzg" + "github.com/consensys/gnark/frontend/cs/scs" + ) + // CubicCircuit defines a simple circuit + // x**3 + x + 5 == y + type CubicCircuit struct { + // struct tags on a variable is optional + // default uses variable name and secret visibility. + X frontend.Variable `gnark:"x"` + Y frontend.Variable `gnark:",public"` + } + // Define declares the circuit constraints + // x**3 + x + 5 == y + func (circuit *CubicCircuit) Define(api frontend.API) error { + x3 := api.Mul(circuit.X, circuit.X, circuit.X) + api.AssertIsEqual(circuit.Y, api.Add(x3, circuit.X, 5)) + return nil + } + func main() { + var circuit CubicCircuit + // use scs.NewBuilder instead of r1cs.NewBuilder (groth16) + ccs, err := frontend.Compile(ecc.BN254.ScalarField(), scs.NewBuilder, &circuit) + if err != nil { + panic("circuit compilation error") + } + // use unsafekzg.NewSRS to generate the SRS and the Lagrange interpolation of the SRS + // Setup prepares the public data associated to a circuit + public inputs. + // The kzg SRS must be provided in canonical and lagrange form. + // For test purposes, see test/unsafekzg package. With an existing SRS generated through MPC in canonical form, + r1cs := ccs.(*cs.SparseR1CS) + srs, srsLagrangeInterpolation, err := unsafekzg.NewSRS(r1cs) + // srs, err := test.NewKZGSRS(r1cs) + if err != nil { + panic("KZG setup error") + } + // add srsLagrangeInterpolation to the Setup function + pk, vk, _ := plonk.Setup(ccs, srs, srsLagrangeInterpolation) + assignment := CubicCircuit{X: 3, Y: 35} + fullWitness, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) + if err != nil { + log.Fatal(err) + } + publicWitness, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField(), frontend.PublicOnly()) + if err != nil { + log.Fatal(err) + } + // This proof should be serialized for testing in the operator + proof, err := plonk.Prove(ccs, pk, fullWitness) + if err != nil { + panic("PLONK proof generation error") + } + // The proof is verified before writing it into a file to make sure it is valid. + err = plonk.Verify(proof, vk, publicWitness) + if err != nil { + panic("PLONK proof not verified") + } + // Open files for writing the proof, the verification key and the public witness + proofFile, err := os.Create("plonk.proof") + if err != nil { + panic(err) + } + vkFile, err := os.Create("plonk.vk") + if err != nil { + panic(err) + } + witnessFile, err := os.Create( "plonk_pub_input.pub") + if err != nil { + panic(err) + } + defer proofFile.Close() + defer vkFile.Close() + defer witnessFile.Close() + _, err = proof.WriteTo(proofFile) + if err != nil { + panic("could not serialize proof into file") + } + _, err = vk.WriteTo(vkFile) + if err != nil { + panic("could not serialize verification key into file") + } + _, err = publicWitness.WriteTo(witnessFile) + if err != nil { + panic("could not serialize proof into file") + } + fmt.Println("Proof written into plonk.proof") + fmt.Println("Verification key written into plonk.vk") + fmt.Println("Public witness written into plonk_pub_input.pub") + } + ``` diff --git a/docs/3_guides/4_generating_proofs.md b/docs/3_guides/4_generating_proofs.md index f0002e862..bf3593739 100644 --- a/docs/3_guides/4_generating_proofs.md +++ b/docs/3_guides/4_generating_proofs.md @@ -41,8 +41,7 @@ aligned submit \ --vm_program \ --batcher_url wss://batcher.alignedlayer.com \ --proof_generator_addr \ ---rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 +--rpc_url https://ethereum-holesky-rpc.publicnode.com ``` Where `proof_path` is the path to the proof file, `vm_program_path` is the path to the ELF file. `proof_generator_addr` is an optional parameter that works as a helper for some applications where you can be frontrunned. @@ -57,10 +56,9 @@ This guide assumes that: - Gnark library is installed. If not, install it using the following command inside your Go module: -```bash -go get github.com/consensys/gnark@v0.11.0 -go get github.com/consensys/gnark-crypto@v0.14.0 -``` + ```bash + go get github.com/consensys/gnark@v0.10.0 + ``` - Gnark project to generate the proofs' instructions [here](https://docs.gnark.consensys.io/category/how-to) @@ -68,9 +66,9 @@ go get github.com/consensys/gnark-crypto@v0.14.0 Open a terminal and navigate to the Gnark project directory. Then, run the following command to generate the proof: -```bash -go run circuit.go -``` + ```bash + go run circuit.go + ``` ### How to get the proof verified by Aligned @@ -92,8 +90,7 @@ aligned submit \ --vk \ --batcher_url wss://batcher.alignedlayer.com \ --proof_generator_addr \ ---rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 +--rpc_url https://ethereum-holesky-rpc.publicnode.com ``` Where proof path is the path to the proof file, `public_input_path` is the path to the public input file, diff --git a/docs/3_guides/6_setup_aligned.md b/docs/3_guides/6_setup_aligned.md index ba2f9eef9..48af08f2b 100644 --- a/docs/3_guides/6_setup_aligned.md +++ b/docs/3_guides/6_setup_aligned.md @@ -415,25 +415,25 @@ make batcher_send_risc0_burst
Plonk -Send an individual bn254 proof: +Send an individual BN254 proof: ```bash make batcher_send_plonk_bn254_task ``` -Send a burst of 15 bn254 proofs: +Send a burst of 15 BN254 proofs: ```bash make batcher_send_plonk_bn254_burst ``` -Send an individual bl12 proof: +Send an individual BLS12-381 proof: ```bash make batcher_send_plonk_bls12_381_task ``` -Send a burst of 15 bl12 proofs: +Send a burst of 15 BLS12-381 proofs: ```bash make batcher_send_plonk_bls12_381_burst @@ -444,19 +444,19 @@ make batcher_send_plonk_bls12_381_burst
Groth16 -Send an individual bn254 proof: +Send an individual BN254 proof: ```bash make batcher_send_groth16_bn254_task ``` -Send bn254 proofs indefinitely: +Send BN254 proofs indefinitely: ```bash make batcher_send_infinite_groth16 ``` -Send bn254 proof bursts indefinitely: +Send BN254 proof bursts indefinitely: ```bash make batcher_send_burst_groth16 @@ -489,8 +489,7 @@ aligned submit \ --batch_inclusion_data_directory_path [batch_inclusion_data_directory_path] \ --keystore_path [path_to_ecdsa_keystore] \ --batcher_url wss://batcher.alignedlayer.com \ ---rpc_url https://ethereum-holesky-rpc.publicnode.com \ ---payment_service_addr 0x815aeCA64a974297942D2Bbf034ABEe22a38A003 +--rpc_url https://ethereum-holesky-rpc.publicnode.com ```
@@ -705,3 +704,19 @@ The state is backed up on `contracts/scripts/anvil/state`. EigenLayer contract deployment is almost the same as the EigenLayer contract deployment on mainnet. Changes are described in the file. + +## Running Fuzzers: + +Fuzzing for the operator can be done by executing the following make commands from the root directory of the project. + +macOS: + +``` +make operator_verification_data_fuzz_macos +``` + +Linux: + +``` +operator_verification_data_fuzz_linux +``` diff --git a/docs/operator_guides/0_running_an_operator.md b/docs/operator_guides/0_running_an_operator.md index da90a7212..e3b9e0785 100644 --- a/docs/operator_guides/0_running_an_operator.md +++ b/docs/operator_guides/0_running_an_operator.md @@ -92,17 +92,27 @@ Update the following placeholders in `./config-files/config-operator.yaml`: `""` and `""` are the paths to your keys generated with the EigenLayer CLI, `""` and `""` can be found in the `operator.yaml` file created in the EigenLayer registration process. The keys are stored by default in the `~/.eigenlayer/operator_keys/` directory, so for example `` could be `/path/to/home/.eigenlayer/operator_keys/some_key.ecdsa.key.json` and for `` it could be `/path/to/home/.eigenlayer/operator_keys/some_key.bls.key.json`. -The default configuration uses the public nodes RPC, but we suggest you use your own nodes for better performance and reliability. -Also, from v0.5.2 there is a fallback mechanism to have two RPCs, so you can add a second RPC for redundancy. +Two RPCs are used, one as the main one, and the other one as a fallback in case one node is working unreliably. + +Default configurations is set up to use the same public node in both scenarios. + +{% hint style="danger" %} + +PUBLIC NODES SHOULDN'T BE USED AS THE MAIN RPC. We recommend not using public nodes at all. + +FALLBACK AND MAIN RPCs SHOULD BE DIFFERENT. + +{% endhint %} + +Most of the actions will pass through the main RPC unless there is a problem with it. Events are fetched from both nodes. ```yaml -eth_rpc_url: "https://ethereum-holesky-rpc.publicnode.com" -eth_rpc_url_fallback: "https://ethereum-holesky-rpc.publicnode.com" -eth_ws_url: "wss://ethereum-holesky-rpc.publicnode.com" -eth_ws_url_fallback: "wss://ethereum-holesky-rpc.publicnode.com" +eth_rpc_url: "https://" +eth_rpc_url_fallback: "https://" +eth_ws_url: "wss://" +eth_ws_url_fallback: "wss://" ``` - ## Step 4 - Deposit Strategy Tokens We are using [WETH](https://holesky.eigenlayer.xyz/restake/WETH) as the strategy token. @@ -152,6 +162,66 @@ If you don't have Holesky ETH, these are some useful faucets: ./operator/build/aligned-operator start --config ./config-files/config-operator.yaml ``` +### Run Operator using Systemd + +To manage the Operator process on Linux systems, we recommend use systemd with the following configuration: + +You should create a user and a group in order to run the Operator and set the service unit to use that. In the provided service unit, we assume you have already created a user called `aligned` + +```toml +# aligned-operator.service + +[Unit] +Description=Aligned Operator +After=network.target + +[Service] +Type=simple +User=aligned +ExecStart=/operator/build/aligned-operator start --config +Restart=always +RestartSec=1 +StartLimitBurst=100 + +[Install] +WantedBy=multi-user.target +``` + +{% hint style="info" %} +`aligned-operator.service` is just an arbitrary name. You can name your service as you wish, following the format `.service`. +{% endhint %} + +Once you have configured the `aligned-operator.service` file, you need to run the following commands: + +```shell +sudo cp aligned-operator.service /etc/systemd/system/aligned-operator.service +sudo systemctl enable --now aligned-operator.service +``` + +{% hint style="warning" %} +All paths must be absolute. +{% endhint %} + +Those commands will link the service to systemd directory and then, will start the Operator service. + +Also, if the server running the operator goes down, systemd will start automatically the Operator on server startup. + +#### Restart operator + +If you want to restart the operator, you can use the following command: + +```shell +sudo systemctl restart aligned-operator.service +``` + +#### Get Operators logs + +Once you are running your operator using systemd, you can get its logs using journalctl as follows: + +```shell +journalctl -xfeu aligned-operator.service +``` + ## Unregistering the operator To unregister the Aligned operator, run: diff --git a/docs/operator_guides/1_operator_FAQ.md b/docs/operator_guides/1_operator_FAQ.md index 5c7f5b64d..79515849f 100644 --- a/docs/operator_guides/1_operator_FAQ.md +++ b/docs/operator_guides/1_operator_FAQ.md @@ -17,9 +17,19 @@ We also recommend the following RPC providers: - [Infura](https://infura.io/) - [Blast](https://blastapi.io/) -The default configuration uses the public nodes RPC. +Two RPCs are used, one as the main one, and the other one as a fallback in case one node is working unreliably. -Since `v0.5.2`, there is a fallback mechanism to have two RPCs, so you need to add a second RPC for redundancy. +Default configurations is set up to use the same public node in both scenarios. + +{% hint style="danger" %} + +PUBLIC NODES SHOULDN'T BE USED AS THE MAIN RPC. We recommend not using public nodes at all. + +FALLBACK AND MAIN RPCs SHOULD BE DIFFERENT. + +{% endhint %} + +Most of the actions will pass through the main RPC unless there is a problem with it. Events are fetched from both nodes. ### How can I check if the version I'm using is the latest one? diff --git a/examples/validating-public-input/aligned-integration/Cargo.lock b/examples/validating-public-input/aligned-integration/Cargo.lock index 2bd528635..2d6e9a36d 100644 --- a/examples/validating-public-input/aligned-integration/Cargo.lock +++ b/examples/validating-public-input/aligned-integration/Cargo.lock @@ -147,13 +147,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.82" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -175,14 +175,14 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" @@ -313,9 +313,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" dependencies = [ "serde", ] @@ -375,9 +375,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.19" +version = "1.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" +checksum = "3bbb537bb4a30b90362caddba8f360c0a56bc13d3a5570028e7197204cb54a17" dependencies = [ "jobserver", "libc", @@ -467,7 +467,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -536,9 +536,9 @@ checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "const-hex" -version = "1.12.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" +checksum = "0121754e84117e65f9d90648ee6aa4882a6e63110307ab73967a4c5e7e69e586" dependencies = [ "cfg-if", "cpufeatures", @@ -688,7 +688,7 @@ checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -997,7 +997,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.77", + "syn 2.0.79", "toml", "walkdir", ] @@ -1014,7 +1014,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1039,7 +1039,7 @@ dependencies = [ "serde", "serde_json", "strum", - "syn 2.0.77", + "syn 2.0.79", "tempfile", "thiserror", "tiny-keccak", @@ -1219,9 +1219,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide", @@ -1339,7 +1339,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1760,9 +1760,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", "ecdsa", @@ -1841,9 +1841,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libm" @@ -2012,7 +2012,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2026,9 +2026,12 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] [[package]] name = "open-fastrlp" @@ -2078,7 +2081,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2258,7 +2261,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2296,7 +2299,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2323,9 +2326,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "powerfmt" @@ -2355,7 +2364,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ "proc-macro2", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2482,9 +2491,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] @@ -2502,9 +2511,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", @@ -2514,9 +2523,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -2525,9 +2534,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" @@ -2847,9 +2856,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -2893,7 +2902,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2916,14 +2925,14 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -3111,7 +3120,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3153,9 +3162,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -3197,9 +3206,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand", @@ -3221,22 +3230,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3318,7 +3327,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3406,9 +3415,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "serde", @@ -3442,7 +3451,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3547,18 +3556,18 @@ checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-xid" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "untrusted" @@ -3664,7 +3673,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-shared", ] @@ -3698,7 +3707,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3906,9 +3915,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -3975,7 +3984,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] diff --git a/examples/zkquiz/quiz/script/Cargo.lock b/examples/zkquiz/quiz/script/Cargo.lock index 8fde6d46c..1bd904465 100644 --- a/examples/zkquiz/quiz/script/Cargo.lock +++ b/examples/zkquiz/quiz/script/Cargo.lock @@ -75,6 +75,7 @@ name = "aligned-sdk" version = "0.1.0" dependencies = [ "ciborium", + "dialoguer", "ethers 2.0.14 (git+https://github.com/yetanotherco/ethers-rs.git?tag=v2.0.15-fix-reconnections)", "futures-util", "hex", diff --git a/examples/zkquiz/quiz/script/src/main.rs b/examples/zkquiz/quiz/script/src/main.rs index b106b3a18..07e565f53 100644 --- a/examples/zkquiz/quiz/script/src/main.rs +++ b/examples/zkquiz/quiz/script/src/main.rs @@ -1,10 +1,12 @@ #![feature(slice_flatten)] use std::io; -use std::str::FromStr; use std::sync::Arc; -use aligned_sdk::core::types::{AlignedVerificationData, Network, ProvingSystemId, VerificationData}; +use aligned_sdk::core::types::{ + AlignedVerificationData, Network, PriceEstimate, ProvingSystemId, VerificationData, +}; +use aligned_sdk::sdk::{estimate_fee, get_payment_service_address}; use aligned_sdk::sdk::{get_next_nonce, submit_and_wait_verification}; use clap::Parser; use dialoguer::Confirm; @@ -13,7 +15,6 @@ use ethers::providers::{Http, Provider}; use ethers::signers::{LocalWallet, Signer}; use ethers::types::{Address, Bytes, H160, U256}; use sp1_sdk::{ProverClient, SP1Stdin}; -use aligned_sdk::sdk::get_payment_service_address; abigen!(VerifierContract, "VerifierContract.json",); @@ -39,7 +40,10 @@ struct Args { #[tokio::main] async fn main() { + println!("Welcome to the zkQuiz! Answer questions, generate a zkProof, and claim your NFT!"); + let args = Args::parse(); + let rpc_url = args.rpc_url.clone(); let keystore_password = rpassword::prompt_password("Enter keystore password: ") .expect("Failed to read keystore password"); @@ -48,10 +52,21 @@ async fn main() { .expect("Failed to decrypt keystore") .with_chain_id(17000u64); + let provider = + Provider::::try_from(rpc_url.as_str()).expect("Failed to connect to provider"); + + let signer = Arc::new(SignerMiddleware::new(provider.clone(), wallet.clone())); + + if Confirm::with_theme(&dialoguer::theme::ColorfulTheme::default()) + .with_prompt("Do you want to deposit 0.004eth in Aligned ?\nIf you already deposited Ethereum to Aligned before, this is not needed") + .interact() + .expect("Failed to read user input") { + deposit_to_batcher(wallet.address(), signer.clone()).await.expect("Failed to pay for proof submission"); + } + // Generate proof. let mut stdin = SP1Stdin::new(); - println!("Welcome to the quiz! Please answer the following questions to generate a proof for the program."); println!( "You will be asked 3 questions. Please answer with the corresponding letter (a, b or c)." ); @@ -70,86 +85,75 @@ async fn main() { user_awnsers.push(ask_question(question3, &answers3)); stdin.write(&user_awnsers); + println!("Generating Proof "); let client = ProverClient::new(); let (pk, vk) = client.setup(ELF); - match client.prove(&pk, stdin).run() { - Ok(proof) => { - println!("Proof generated successfully. Verifying proof..."); - - client.verify(&proof, &vk).expect("verification failed"); - - println!("Proof verified successfully."); - - let rpc_url = args.rpc_url.clone(); - - let provider = Provider::::try_from(rpc_url.as_str()) - .expect("Failed to connect to provider"); - - let signer = Arc::new(SignerMiddleware::new(provider.clone(), wallet.clone())); - - // Pay for proof submission - pay_batcher(wallet.address(), signer.clone()) - .await - .expect("Failed to pay for proof submission"); - - println!("Payment successful. Submitting proof..."); - - // Serialize proof into bincode (format used by sp1) - let proof = bincode::serialize(&proof).expect("Failed to serialize proof"); - - let verification_data = VerificationData { - proving_system: ProvingSystemId::SP1, - proof, - proof_generator_addr: wallet.address(), - vm_program_code: Some(ELF.to_vec()), - verification_key: None, - pub_input: None, - }; - - // Set a `max_fee` of 0.5 Eth - let max_fee = U256::from(5) * U256::from(100_000_000_000_000_000u128); - let nonce = get_next_nonce(&rpc_url, wallet.address(), NETWORK) - .await - .expect("Failed to get next nonce"); - - match submit_and_wait_verification( - BATCHER_URL, - &rpc_url, - NETWORK, - &verification_data, - max_fee, - wallet.clone(), - nonce, - ) - .await - { - Ok(aligned_verification_data) => { - println!( - "Proof submitted and verified successfully on batch {}, claiming prize...", - hex::encode(aligned_verification_data.batch_merkle_root) - ); - - if let Err(e) = verify_batch_inclusion( - aligned_verification_data.clone(), - signer.clone(), - args.verifier_contract_address, - ) - .await - { - println!("Failed to claim prize: {:?}", e); - } - } - Err(e) => { - println!("Proof verification failed: {:?}", e); - } - } - } - Err(_) => { - println!("Proof generation failed. Incorrect answer"); - } - } + + let Ok(proof) = client.prove(&pk, stdin).run() else { + println!("Incorrect answers!"); + return; + }; + + println!("Proof generated successfully. Verifying proof..."); + client.verify(&proof, &vk).expect("verification failed"); + println!("Proof verified successfully."); + + println!("Payment successful. Submitting proof..."); + + // Serialize proof into bincode (format used by sp1) + let proof = bincode::serialize(&proof).expect("Failed to serialize proof"); + + let verification_data = VerificationData { + proving_system: ProvingSystemId::SP1, + proof, + proof_generator_addr: wallet.address(), + vm_program_code: Some(ELF.to_vec()), + verification_key: None, + pub_input: None, + }; + + let max_fee = estimate_fee(&rpc_url, PriceEstimate::Default) + .await + .expect("failed to fetch gas price from the blockchain"); + + let max_fee_string = ethers::utils::format_units(max_fee, 18).unwrap(); + + if !Confirm::with_theme(&dialoguer::theme::ColorfulTheme::default()) + .with_prompt(format!("Aligned will use at most {max_fee_string} eth to verify your proof. Do you want to continue?")) + .interact() + .expect("Failed to read user input") + { return; } + + let nonce = get_next_nonce(&rpc_url, wallet.address(), NETWORK) + .await + .expect("Failed to get next nonce"); + + let aligned_verification_data = submit_and_wait_verification( + BATCHER_URL, + &rpc_url, + NETWORK, + &verification_data, + max_fee, + wallet.clone(), + nonce, + ) + .await + .unwrap(); + + println!( + "Proof submitted and verified successfully on batch {}, claiming prize...", + hex::encode(aligned_verification_data.batch_merkle_root) + ); + + claim_nft_with_verified_proof( + &aligned_verification_data, + signer, + &args.verifier_contract_address, + ) + .await + .expect("Claiming of NFT failed ..."); } fn ask_question(question: &str, answers: &[&str]) -> char { @@ -189,18 +193,10 @@ fn read_answer() -> char { } } -async fn pay_batcher( +async fn deposit_to_batcher( from: Address, signer: Arc, LocalWallet>>, ) -> anyhow::Result<()> { - if !Confirm::with_theme(&dialoguer::theme::ColorfulTheme::default()) - .with_prompt("We are going to pay 0.004eth for the proof submission to aligned. Do you want to continue?") - .interact() - .expect("Failed to read user input") - { - anyhow::bail!("Payment cancelled") - } - let addr = get_payment_service_address(NETWORK); let tx = TransactionRequest::new() @@ -228,12 +224,12 @@ async fn pay_batcher( } } -async fn verify_batch_inclusion( - aligned_verification_data: AlignedVerificationData, +async fn claim_nft_with_verified_proof( + aligned_verification_data: &AlignedVerificationData, signer: Arc, LocalWallet>>, - verifier_contract_addr: Address, + verifier_contract_addr: &Address, ) -> anyhow::Result<()> { - let verifier_contract = VerifierContract::new(verifier_contract_addr, signer); + let verifier_contract = VerifierContract::new(*verifier_contract_addr, signer); let index_in_batch = U256::from(aligned_verification_data.index_in_batch); let merkle_path = Bytes::from( diff --git a/go.mod b/go.mod index 49da66f83..502e791b0 100644 --- a/go.mod +++ b/go.mod @@ -3,16 +3,18 @@ module github.com/yetanotherco/aligned_layer go 1.22.2 require ( - github.com/Layr-Labs/eigensdk-go v0.1.9 + github.com/Layr-Labs/eigensdk-go v0.1.12 github.com/ethereum/go-ethereum v1.14.0 github.com/prometheus/client_golang v1.19.1 github.com/urfave/cli/v2 v2.27.1 - golang.org/x/crypto v0.26.0 + golang.org/x/crypto v0.22.0 ) require ( - github.com/consensys/gnark v0.11.0 - github.com/consensys/gnark-crypto v0.14.0 + github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 + github.com/consensys/gnark v0.10.0 + github.com/consensys/gnark-crypto v0.12.2-0.20240215234832-d72fcb379d3e + github.com/fxamacker/cbor/v2 v2.7.0 github.com/ugorji/go/codec v1.2.12 ) @@ -35,26 +37,25 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 // indirect github.com/aws/smithy-go v1.20.2 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.14.2 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect - github.com/crate-crypto/go-kzg-4844 v1.1.0 // indirect + github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect - github.com/ethereum/c-kzg-4844 v1.0.3 // indirect + github.com/ethereum/c-kzg-4844 v1.0.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect - github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect + github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/holiman/uint256 v1.2.4 // indirect - github.com/ingonyama-zk/icicle v1.1.0 // indirect + github.com/ingonyama-zk/icicle v0.0.0-20230928131117-97f0079e5c71 // indirect github.com/ingonyama-zk/iciclegnark v0.1.0 // indirect github.com/klauspost/compress v1.17.7 // indirect github.com/lmittmann/tint v1.0.4 // indirect @@ -67,12 +68,12 @@ require ( github.com/prometheus/common v0.52.2 // indirect github.com/prometheus/procfs v0.13.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect - github.com/ronanh/intcomp v1.1.0 // indirect github.com/rs/cors v1.8.3 // indirect - github.com/rs/zerolog v1.33.0 // indirect + github.com/rs/zerolog v1.32.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shirou/gopsutil v3.21.6+incompatible // indirect github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 // indirect + github.com/stretchr/testify v1.9.0 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect @@ -81,15 +82,14 @@ require ( github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/mod v0.20.0 // indirect - golang.org/x/net v0.28.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.24.0 // indirect - golang.org/x/tools v0.24.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/tools v0.20.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) - -replace github.com/Layr-Labs/eigensdk-go => github.com/yetanotherco/eigensdk-go v0.1.10-0.20240805154752-29f4d3457921 diff --git a/go.sum b/go.sum index ee02f6995..dceaadc81 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,13 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/Layr-Labs/eigensdk-go v0.1.12 h1:Drf59iJLvnTm2Om9AwAyUMiZeJaTI8ZameIrnhjopSY= +github.com/Layr-Labs/eigensdk-go v0.1.12/go.mod h1:XcLVDtlB1vOPj63D236b451+SC75B8gwgkpNhYHSxNs= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= @@ -42,8 +46,8 @@ github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.14.2 h1:YXVoyPndbdvcEVcseEovVfp0qjJp7S+i5+xgp/Nfbdc= -github.com/bits-and-blooms/bitset v1.14.2/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= @@ -71,10 +75,10 @@ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAK github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark v0.11.0 h1:YlndnlbRAoIEA+aIIHzNIW4P0dCIOM9/jCVzsXf356c= -github.com/consensys/gnark v0.11.0/go.mod h1:2LbheIOxsBI1a9Ck1XxUoy6PRnH28mSI9qrvtN2HwDY= -github.com/consensys/gnark-crypto v0.14.0 h1:DDBdl4HaBtdQsq/wfMwJvZNE80sHidrK3Nfrefatm0E= -github.com/consensys/gnark-crypto v0.14.0/go.mod h1:CU4UijNPsHawiVGNxe9co07FkzCeWHHrb1li/n1XoU0= +github.com/consensys/gnark v0.10.0 h1:yhi6ThoeFP7WrH8zQDaO56WVXe9iJEBSkfrZ9PZxabw= +github.com/consensys/gnark v0.10.0/go.mod h1:VJU5JrrhZorbfDH+EUjcuFWr2c5z19tHPh8D6KVQksU= +github.com/consensys/gnark-crypto v0.12.2-0.20240215234832-d72fcb379d3e h1:MKdOuCiy2DAX1tMp2YsmtNDaqdigpY6B5cZQDJ9BvEo= +github.com/consensys/gnark-crypto v0.12.2-0.20240215234832-d72fcb379d3e/go.mod h1:wKqwsieaKPThcFkHe0d0zMsbHEUWFmZcG7KBCse210o= github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= @@ -86,8 +90,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0q github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= -github.com/crate-crypto/go-kzg-4844 v1.1.0 h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHHlMnHfoyU4= -github.com/crate-crypto/go-kzg-4844 v1.1.0/go.mod h1:JolLjpSff1tCCJKaJx4psrlEdlXuJEC996PL3tTAFks= +github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI= +github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -106,8 +110,8 @@ github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/ethereum/c-kzg-4844 v1.0.3 h1:IEnbOHwjixW2cTvKRUlAAUOeleV7nNM/umJR+qy4WDs= -github.com/ethereum/c-kzg-4844 v1.0.3/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= +github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-ethereum v1.14.0 h1:xRWC5NlB6g1x7vNy4HDBLuqVNbtLrc7v8S6+Uxim1LU= github.com/ethereum/go-ethereum v1.14.0/go.mod h1:1STrq471D0BQbCX9He0hUj4bHxX2k6mt5nOQJhDNOJ8= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -167,8 +171,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= -github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo= +github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -186,8 +190,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ingonyama-zk/icicle v1.1.0 h1:a2MUIaF+1i4JY2Lnb961ZMvaC8GFs9GqZgSnd9e95C8= -github.com/ingonyama-zk/icicle v1.1.0/go.mod h1:kAK8/EoN7fUEmakzgZIYdWy1a2rBnpCaZLqSHwZWxEk= +github.com/ingonyama-zk/icicle v0.0.0-20230928131117-97f0079e5c71 h1:YxI1RTPzpFJ3MBmxPl3Bo0F7ume7CmQEC1M9jL6CT94= +github.com/ingonyama-zk/icicle v0.0.0-20230928131117-97f0079e5c71/go.mod h1:kAK8/EoN7fUEmakzgZIYdWy1a2rBnpCaZLqSHwZWxEk= github.com/ingonyama-zk/iciclegnark v0.1.0 h1:88MkEghzjQBMjrYRJFxZ9oR9CTIpB8NG2zLeCJSvXKQ= github.com/ingonyama-zk/iciclegnark v0.1.0/go.mod h1:wz6+IpyHKs6UhMMoQpNqz1VY+ddfKqC/gRwR/64W6WU= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= @@ -200,8 +204,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= -github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/lmittmann/tint v1.0.4 h1:LeYihpJ9hyGvE0w+K2okPTGUdVLfng1+nDNVR4vWISc= github.com/lmittmann/tint v1.0.4/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= @@ -267,15 +271,13 @@ github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGK github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/ronanh/intcomp v1.1.0 h1:i54kxmpmSoOZFcWPMWryuakN0vLxLswASsGa07zkvLU= -github.com/ronanh/intcomp v1.1.0/go.mod h1:7FOLy3P3Zj3er/kVrU/pl+Ql7JFZj7bwliMGketo0IU= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= -github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shirou/gopsutil v3.21.6+incompatible h1:mmZtAlWSd8U2HeRTjswbnDLPxqsEoK01NK+GZ1P+nEM= @@ -315,8 +317,6 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yetanotherco/eigensdk-go v0.1.10-0.20240805154752-29f4d3457921 h1:bYER70hS8+Qx//uWWhm0+WymLTKHiqfbJkphteKUxPc= -github.com/yetanotherco/eigensdk-go v0.1.10-0.20240805154752-29f4d3457921/go.mod h1:XcLVDtlB1vOPj63D236b451+SC75B8gwgkpNhYHSxNs= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= @@ -339,13 +339,13 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 h1:kx6Ds3MlpiUHKj7syVnbp57++8WpuKPcR5yjLBjvLEA= -golang.org/x/exp v0.0.0-20240823005443-9b4947da3948/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -354,13 +354,13 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -384,23 +384,23 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/operator/cmd/actions/deposit_into_strategy.go b/operator/cmd/actions/deposit_into_strategy.go index 47e2ffde5..d80ba6ffc 100644 --- a/operator/cmd/actions/deposit_into_strategy.go +++ b/operator/cmd/actions/deposit_into_strategy.go @@ -69,23 +69,23 @@ func depositIntoStrategyMain(ctx *cli.Context) error { if err != nil { return err } - w, err := wallet.NewPrivateKeyWallet(config.BaseConfig.EthRpcClient, signerFn, + w, err := wallet.NewPrivateKeyWallet(&config.BaseConfig.EthRpcClient, signerFn, config.Operator.Address, config.BaseConfig.Logger) if err != nil { return err } - txMgr := txmgr.NewSimpleTxManager(w, config.BaseConfig.EthRpcClient, config.BaseConfig.Logger, + txMgr := txmgr.NewSimpleTxManager(w, &config.BaseConfig.EthRpcClient, config.BaseConfig.Logger, config.Operator.Address) eigenMetrics := metrics.NewNoopMetrics() eigenLayerWriter, err := elcontracts.BuildELChainWriter(delegationManagerAddr, avsDirectoryAddr, - config.BaseConfig.EthRpcClient, config.BaseConfig.Logger, eigenMetrics, txMgr) + &config.BaseConfig.EthRpcClient, config.BaseConfig.Logger, eigenMetrics, txMgr) if err != nil { return err } - _, err = eigenLayerWriter.DepositERC20IntoStrategy(context.Background(), strategyAddr, amount) + _, err = eigenLayerWriter.DepositERC20IntoStrategy(context.Background(), strategyAddr, amount, true) if err != nil { config.BaseConfig.Logger.Errorf("Error depositing into strategy") return err diff --git a/operator/merkle_tree/lib/test_files/merkle_root.bin b/operator/merkle_tree/lib/test_files/merkle_root.bin index 7d46ceeae..623903edd 100644 --- a/operator/merkle_tree/lib/test_files/merkle_root.bin +++ b/operator/merkle_tree/lib/test_files/merkle_root.bin @@ -1 +1 @@ -e0a3761a514a2a7873350869e699bbd87c9cbf53ba963caae0a232cb6d698b1b \ No newline at end of file +715181f01c095618472a72cd06e384d92f02eadc4ea28bf097181b17fdc57f28 \ No newline at end of file diff --git a/operator/merkle_tree/lib/test_files/merkle_tree_batch.bin b/operator/merkle_tree/lib/test_files/merkle_tree_batch.bin index 7238a17a1..733703c54 100644 Binary files a/operator/merkle_tree/lib/test_files/merkle_tree_batch.bin and b/operator/merkle_tree/lib/test_files/merkle_tree_batch.bin differ diff --git a/operator/merkle_tree/merkle_tree.go b/operator/merkle_tree/merkle_tree.go index 7eb40772d..9b6562481 100644 --- a/operator/merkle_tree/merkle_tree.go +++ b/operator/merkle_tree/merkle_tree.go @@ -9,12 +9,12 @@ package merkle_tree import "C" import "unsafe" -func VerifyMerkleTreeBatch(batchBuffer []byte, batchLen uint, merkleRootBuffer [32]byte) bool { +func VerifyMerkleTreeBatch(batchBuffer []byte, merkleRootBuffer [32]byte) bool { if len(batchBuffer) == 0 { return false } batchPtr := (*C.uchar)(unsafe.Pointer(&batchBuffer[0])) merkleRootPtr := (*C.uchar)(unsafe.Pointer(&merkleRootBuffer[0])) - return (bool)(C.verify_merkle_tree_batch_ffi(batchPtr, (C.uint)(batchLen), merkleRootPtr)) + return (bool)(C.verify_merkle_tree_batch_ffi(batchPtr, (C.uint)(len(batchBuffer)), merkleRootPtr)) } diff --git a/operator/merkle_tree/merkle_tree_test.go b/operator/merkle_tree/merkle_tree_test.go index 0faa5f49a..539391929 100644 --- a/operator/merkle_tree/merkle_tree_test.go +++ b/operator/merkle_tree/merkle_tree_test.go @@ -3,28 +3,21 @@ package merkle_tree import ( "encoding/hex" "fmt" - "io" "os" "testing" ) -func TestVerifyMerkleTreeBatch(t *testing.T) { - batchFile, err := os.Open("lib/test_files/merkle_tree_batch.bin") - if err != nil { - t.Fatalf("Error opening batch file: %v", err) - } +const BatchFilePath = "lib/test_files/merkle_tree_batch.bin" - batchByteValue, err := io.ReadAll(batchFile) - if err != nil { - t.Fatalf("Error reading batch file: %v", err) - } +const RootFilePath = "lib/test_files/merkle_root.bin" - rootFile, err := os.Open("lib/test_files/merkle_root.bin") +func TestVerifyMerkleTreeBatch(t *testing.T) { + batchByteValue, err := os.ReadFile(BatchFilePath) if err != nil { - t.Fatalf("Error opening batch file: %v", err) + t.Fatalf("Error reading batch file: %v", err) } - rootByteValue, err := io.ReadAll(rootFile) + rootByteValue, err := os.ReadFile(RootFilePath) if err != nil { t.Fatalf("Error reading batch file: %v", err) } @@ -39,7 +32,7 @@ func TestVerifyMerkleTreeBatch(t *testing.T) { var merkleRoot [32]byte copy(merkleRoot[:], merkle_root) - if !VerifyMerkleTreeBatch(batchByteValue, uint(len(batchByteValue)), merkleRoot) { + if !VerifyMerkleTreeBatch(batchByteValue, merkleRoot) { t.Errorf("Batch did not verify Merkle Root") } diff --git a/operator/merkle_tree_old/merkle_tree_old.go b/operator/merkle_tree_old/merkle_tree_old.go index 80fb227e3..d97d48e69 100644 --- a/operator/merkle_tree_old/merkle_tree_old.go +++ b/operator/merkle_tree_old/merkle_tree_old.go @@ -9,12 +9,12 @@ package merkle_tree_old import "C" import "unsafe" -func VerifyMerkleTreeBatchOld(batchBuffer []byte, batchLen uint, merkleRootBuffer [32]byte) bool { +func VerifyMerkleTreeBatchOld(batchBuffer []byte, merkleRootBuffer [32]byte) bool { if len(batchBuffer) == 0 { return false } batchPtr := (*C.uchar)(unsafe.Pointer(&batchBuffer[0])) merkleRootPtr := (*C.uchar)(unsafe.Pointer(&merkleRootBuffer[0])) - return (bool)(C.verify_merkle_tree_batch_ffi_old(batchPtr, (C.uint)(batchLen), merkleRootPtr)) + return (bool)(C.verify_merkle_tree_batch_ffi_old(batchPtr, (C.uint)(len(batchBuffer)), merkleRootPtr)) } diff --git a/operator/merkle_tree_old/merkle_tree_old_test.go b/operator/merkle_tree_old/merkle_tree_old_test.go index 3d7f97a87..0f4e2a8f6 100644 --- a/operator/merkle_tree_old/merkle_tree_old_test.go +++ b/operator/merkle_tree_old/merkle_tree_old_test.go @@ -3,30 +3,23 @@ package merkle_tree_old import ( "encoding/hex" "fmt" - "io" "os" "testing" ) -func TestVerifyMerkleTreeBatchOld(t *testing.T) { - batchFile, err := os.Open("lib/test_files/merkle_tree_batch.bin") - if err != nil { - t.Fatalf("Error opening batch file: %v", err) - } +const BatchFilePath = "lib/test_files/merkle_tree_batch.bin" - batchByteValue, err := io.ReadAll(batchFile) - if err != nil { - t.Fatalf("Error reading batch file: %v", err) - } +const RootFilePath = "lib/test_files/merkle_root.bin" - rootFile, err := os.Open("lib/test_files/merkle_root.bin") +func TestVerifyMerkleTreeBatchOld(t *testing.T) { + batchByteValue, err := os.ReadFile(BatchFilePath) if err != nil { t.Fatalf("Error opening batch file: %v", err) } - rootByteValue, err := io.ReadAll(rootFile) + rootByteValue, err := os.ReadFile(RootFilePath) if err != nil { - t.Fatalf("Error reading batch file: %v", err) + t.Fatalf("Error opening batch file: %v", err) } merkle_root := make([]byte, hex.DecodedLen(len(rootByteValue))) @@ -39,7 +32,7 @@ func TestVerifyMerkleTreeBatchOld(t *testing.T) { var merkleRoot [32]byte copy(merkleRoot[:], merkle_root) - if !VerifyMerkleTreeBatchOld(batchByteValue, uint(len(batchByteValue)), merkleRoot) { + if !VerifyMerkleTreeBatchOld(batchByteValue, merkleRoot) { t.Errorf("Batch did not verify Merkle Root") } diff --git a/operator/pkg/codec_mode.go b/operator/pkg/codec_mode.go new file mode 100644 index 000000000..17f02ce17 --- /dev/null +++ b/operator/pkg/codec_mode.go @@ -0,0 +1,10 @@ +package operator + +import ( + "github.com/fxamacker/cbor/v2" +) + +func createDecoderMode() (cbor.DecMode, error) { + // Use the max value for length of an array to correctly decode the batch. + return cbor.DecOptions{MaxArrayElements: 2147483647}.DecMode() +} diff --git a/operator/pkg/marshall_unmarshall_health_test.go b/operator/pkg/marshall_unmarshall_health_test.go new file mode 100644 index 000000000..da39971cb --- /dev/null +++ b/operator/pkg/marshall_unmarshall_health_test.go @@ -0,0 +1,32 @@ +package operator + +import ( + "bytes" + "testing" + + "github.com/fxamacker/cbor/v2" +) + +// Test roundtrip of cbor serialization and deserialization used in Aligned to verify that it doesn't panic. +func FuzzMarshalUnmarshal(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte, seed int64) { + // MarshalUnmarshal + + var unmarshalled VerificationData + decoder, err := createDecoderMode() + if err != nil { + return + } + err = decoder.Unmarshal(data, &unmarshalled) + if err != nil { + return + } + + var marshalled []byte + encoder := cbor.NewEncoder(bytes.NewBuffer(marshalled)) + err = encoder.Encode(&unmarshalled) + if err != nil { + return + } + }) +} diff --git a/operator/pkg/operator.go b/operator/pkg/operator.go index b72b3c724..3a562460d 100644 --- a/operator/pkg/operator.go +++ b/operator/pkg/operator.go @@ -345,24 +345,18 @@ func (o *Operator) verify(verificationData VerificationData, results chan bool) case common.Groth16Bn254: verificationResult := o.verifyGroth16ProofBN254(verificationData.Proof, verificationData.PubInput, verificationData.VerificationKey) - o.Logger.Infof("GROTH16 BN254 proof verification result: %t", verificationResult) + results <- verificationResult case common.SP1: - proofLen := (uint32)(len(verificationData.Proof)) - elfLen := (uint32)(len(verificationData.VmProgramCode)) - - verificationResult := sp1.VerifySp1Proof(verificationData.Proof, proofLen, verificationData.VmProgramCode, elfLen) + verificationResult := sp1.VerifySp1Proof(verificationData.Proof, verificationData.VmProgramCode) o.Logger.Infof("SP1 proof verification result: %t", verificationResult) results <- verificationResult - case common.Risc0: - proofLen := (uint32)(len(verificationData.Proof)) - imageIdLen := (uint32)(len(verificationData.VmProgramCode)) - pubInputLen := (uint32)(len(verificationData.PubInput)) - verificationResult := risc_zero.VerifyRiscZeroReceipt(verificationData.Proof, proofLen, - verificationData.VmProgramCode, imageIdLen, verificationData.PubInput, pubInputLen) + case common.Risc0: + verificationResult := risc_zero.VerifyRiscZeroReceipt(verificationData.Proof, + verificationData.VmProgramCode, verificationData.PubInput) o.Logger.Infof("Risc0 proof verification result: %t", verificationResult) results <- verificationResult diff --git a/operator/pkg/register.go b/operator/pkg/register.go index 1a8275515..76a0af3e1 100644 --- a/operator/pkg/register.go +++ b/operator/pkg/register.go @@ -2,8 +2,6 @@ package operator import ( "context" - "math/big" - "time" "github.com/Layr-Labs/eigensdk-go/types" "github.com/yetanotherco/aligned_layer/core/chainio" @@ -25,14 +23,13 @@ func RegisterOperator( return err } - operatorToAvsRegistrationSigExpiry := big.NewInt(time.Now().Add(10 * time.Minute).Unix()) socket := "Not Needed" quorumNumbers := types.QuorumNums{0} - _, err = writer.RegisterOperatorInQuorumWithAVSRegistryCoordinator(ctx, configuration.EcdsaConfig.PrivateKey, - operatorToAvsRegistrationSigSalt, operatorToAvsRegistrationSigExpiry, configuration.BlsConfig.KeyPair, - quorumNumbers, socket) + _, err = writer.RegisterOperator(ctx, configuration.EcdsaConfig.PrivateKey, + configuration.BlsConfig.KeyPair, + quorumNumbers, socket, true) if err != nil { configuration.BaseConfig.Logger.Error("Failed to register operator", "err", err) diff --git a/operator/pkg/s3.go b/operator/pkg/s3.go index 157cd6674..a3de5198c 100644 --- a/operator/pkg/s3.go +++ b/operator/pkg/s3.go @@ -8,7 +8,6 @@ import ( "time" "github.com/ugorji/go/codec" - "github.com/yetanotherco/aligned_layer/operator/merkle_tree" merkle_tree_old "github.com/yetanotherco/aligned_layer/operator/merkle_tree_old" ) @@ -92,11 +91,11 @@ func (o *Operator) getBatchFromDataService(ctx context.Context, batchURL string, // Checks if downloaded merkle root is the same as the expected one o.Logger.Infof("Verifying batch merkle tree...") - merkle_root_check := merkle_tree.VerifyMerkleTreeBatch(batchBytes, uint(len(batchBytes)), expectedMerkleRoot) + merkle_root_check := merkle_tree.VerifyMerkleTreeBatch(batchBytes, expectedMerkleRoot) if !merkle_root_check { // try old merkle tree o.Logger.Infof("Batch merkle tree verification failed. Trying old merkle tree...") - merkle_root_check = merkle_tree_old.VerifyMerkleTreeBatchOld(batchBytes, uint(len(batchBytes)), expectedMerkleRoot) + merkle_root_check = merkle_tree_old.VerifyMerkleTreeBatchOld(batchBytes, expectedMerkleRoot) if !merkle_root_check { return nil, fmt.Errorf("merkle root check failed") } @@ -105,13 +104,16 @@ func (o *Operator) getBatchFromDataService(ctx context.Context, batchURL string, var batch []VerificationData - decoder := codec.NewDecoderBytes(batchBytes, new(codec.CborHandle)) + decoder, err := createDecoderMode() + if err != nil { + return nil, fmt.Errorf("error creating CBOR decoder: %s", err) + } + err = decoder.Unmarshal(batchBytes, &batch) - err = decoder.Decode(&batch) if err != nil { o.Logger.Infof("Error decoding batch as CBOR: %s. Trying JSON decoding...", err) // try json - decoder = codec.NewDecoderBytes(batchBytes, new(codec.JsonHandle)) + decoder := codec.NewDecoderBytes(batchBytes, new(codec.JsonHandle)) err = decoder.Decode(&batch) if err != nil { return nil, err diff --git a/operator/pkg/valid_marshall_test.go b/operator/pkg/valid_marshall_test.go new file mode 100644 index 000000000..02bf4c498 --- /dev/null +++ b/operator/pkg/valid_marshall_test.go @@ -0,0 +1,32 @@ +package operator + +import ( + "bytes" + "testing" + + fuzz "github.com/AdaLogics/go-fuzz-headers" + "github.com/fxamacker/cbor/v2" +) + +// Test roundtrip of cbor serialization used in Aligned to check correctness. +func FuzzValidMarshall(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte, seed int64) { + fz := fuzz.NewConsumer(data) + var verification_data VerificationData + err := fz.GenerateStruct(&verification_data) + if err != nil { + return + } + + var marshalled []byte + encoder := cbor.NewEncoder(bytes.NewBuffer(marshalled)) + err = encoder.Encode(&verification_data) + if err != nil { + return + } + + if len(data) != 0 && !bytes.Equal(data, marshalled) { + t.Fatalf("data and marshalled are not equal. data[%d]: [%v], marshalled[%d]: [%s]", len(data), data, len(marshalled), marshalled) + } + }) +} diff --git a/operator/risc_zero/lib/src/lib.rs b/operator/risc_zero/lib/src/lib.rs index 9bf8c4894..13be1cafc 100644 --- a/operator/risc_zero/lib/src/lib.rs +++ b/operator/risc_zero/lib/src/lib.rs @@ -1,5 +1,5 @@ -use risc0_zkvm::{InnerReceipt, Receipt}; use log::error; +use risc0_zkvm::{InnerReceipt, Receipt}; #[no_mangle] pub extern "C" fn verify_risc_zero_receipt_ffi( @@ -20,13 +20,11 @@ pub extern "C" fn verify_risc_zero_receipt_ffi( return false; } - let mut public_input: *const u8 = public_input; - let mut public_input_len: u32 = public_input_len; - if public_input.is_null() || public_input_len == 0 { - // set public input to pointer to empty slice - let empty_slice: &[u8] = &[]; - public_input = empty_slice.as_ptr(); - public_input_len = 0; + //NOTE: We allow the public input for risc0 to be empty. + let mut public_input_slice: &[u8] = &[]; + if !public_input.is_null() && public_input_len > 0 { + public_input_slice = + unsafe { std::slice::from_raw_parts(public_input, public_input_len as usize) }; } let inner_receipt_bytes = @@ -34,14 +32,11 @@ pub extern "C" fn verify_risc_zero_receipt_ffi( let image_id = unsafe { std::slice::from_raw_parts(image_id, image_id_len as usize) }; - let public_input = - unsafe { std::slice::from_raw_parts(public_input, public_input_len as usize) }; - let mut image_id_array = [0u8; 32]; image_id_array.copy_from_slice(image_id); if let Ok(inner_receipt) = bincode::deserialize::(inner_receipt_bytes) { - let receipt = Receipt::new(inner_receipt, public_input.to_vec()); + let receipt = Receipt::new(inner_receipt, public_input_slice.to_vec()); return receipt.verify(image_id_array).is_ok(); } @@ -93,4 +88,21 @@ mod tests { ); assert!(!result) } + + #[test] + fn verify_risc_zero_input_valid() { + let receipt_bytes = RECEIPT.as_ptr(); + let image_id = IMAGE_ID.as_ptr(); + let public_input = [].as_ptr(); + + let result = verify_risc_zero_receipt_ffi( + receipt_bytes, + (RECEIPT.len() - 1) as u32, + image_id, + IMAGE_ID.len() as u32, + public_input, + 0, + ); + assert!(!result) + } } diff --git a/operator/risc_zero/risc_zero.go b/operator/risc_zero/risc_zero.go index 35a143e3b..92716ae02 100644 --- a/operator/risc_zero/risc_zero.go +++ b/operator/risc_zero/risc_zero.go @@ -11,7 +11,7 @@ import ( "unsafe" ) -func VerifyRiscZeroReceipt(innerReceiptBuffer []byte, innerReceiptLen uint32, imageIdBuffer []byte, imageIdLen uint32, publicInput []byte, publicInputLen uint32) bool { +func VerifyRiscZeroReceipt(innerReceiptBuffer []byte, imageIdBuffer []byte, publicInputBuffer []byte) bool { if len(innerReceiptBuffer) == 0 || len(imageIdBuffer) == 0 { return false } @@ -19,10 +19,10 @@ func VerifyRiscZeroReceipt(innerReceiptBuffer []byte, innerReceiptLen uint32, im receiptPtr := (*C.uchar)(unsafe.Pointer(&innerReceiptBuffer[0])) imageIdPtr := (*C.uchar)(unsafe.Pointer(&imageIdBuffer[0])) - if len(publicInput) == 0 { // allow empty public input - return (bool)(C.verify_risc_zero_receipt_ffi(receiptPtr, (C.uint32_t)(innerReceiptLen), imageIdPtr, (C.uint32_t)(imageIdLen), nil, (C.uint32_t)(0))) + if len(publicInputBuffer) == 0 { // allow empty public input + return (bool)(C.verify_risc_zero_receipt_ffi(receiptPtr, (C.uint32_t)(len(innerReceiptBuffer)), imageIdPtr, (C.uint32_t)(len(imageIdBuffer)), nil, (C.uint32_t)(0))) } - publicInputPtr := (*C.uchar)(unsafe.Pointer(&publicInput[0])) - return (bool)(C.verify_risc_zero_receipt_ffi(receiptPtr, (C.uint32_t)(innerReceiptLen), imageIdPtr, (C.uint32_t)(imageIdLen), publicInputPtr, (C.uint32_t)(publicInputLen))) + publicInputPtr := (*C.uchar)(unsafe.Pointer(&publicInputBuffer[0])) + return (bool)(C.verify_risc_zero_receipt_ffi(receiptPtr, (C.uint32_t)(len(innerReceiptBuffer)), imageIdPtr, (C.uint32_t)(len(imageIdBuffer)), publicInputPtr, (C.uint32_t)(len(publicInputBuffer)))) } diff --git a/operator/risc_zero/risc_zero_test.go b/operator/risc_zero/risc_zero_test.go index b175ff558..cb83a06f5 100644 --- a/operator/risc_zero/risc_zero_test.go +++ b/operator/risc_zero/risc_zero_test.go @@ -23,7 +23,7 @@ func TestFibonacciRiscZeroProofVerifies(t *testing.T) { t.Errorf("could not open public input file: %s", err) } - if !risc_zero.VerifyRiscZeroReceipt(innerReceiptBytes, uint32(len(innerReceiptBytes)), imageIdBytes, uint32(len(imageIdBytes)), publicInputBytes, uint32(len(publicInputBytes))) { + if !risc_zero.VerifyRiscZeroReceipt(innerReceiptBytes, imageIdBytes, publicInputBytes) { t.Errorf("proof did not verify") } } diff --git a/operator/sp1/lib/src/lib.rs b/operator/sp1/lib/src/lib.rs index cf8ee348c..c3145a00c 100644 --- a/operator/sp1/lib/src/lib.rs +++ b/operator/sp1/lib/src/lib.rs @@ -1,7 +1,6 @@ use lazy_static::lazy_static; -use sp1_sdk::ProverClient; -use std::slice; use log::error; +use sp1_sdk::ProverClient; lazy_static! { static ref PROVER_CLIENT: ProverClient = ProverClient::new(); @@ -24,9 +23,9 @@ pub extern "C" fn verify_sp1_proof_ffi( return false; } - let proof_bytes = unsafe { slice::from_raw_parts(proof_bytes, proof_len as usize) }; + let proof_bytes = unsafe { std::slice::from_raw_parts(proof_bytes, proof_len as usize) }; - let elf_bytes = unsafe { slice::from_raw_parts(elf_bytes, elf_len as usize) }; + let elf_bytes = unsafe { std::slice::from_raw_parts(elf_bytes, elf_len as usize) }; if let Ok(proof) = bincode::deserialize(proof_bytes) { let (_pk, vk) = PROVER_CLIENT.setup(elf_bytes); diff --git a/operator/sp1/sp1.go b/operator/sp1/sp1.go index 4340e9a47..64b310844 100644 --- a/operator/sp1/sp1.go +++ b/operator/sp1/sp1.go @@ -9,7 +9,7 @@ package sp1 import "C" import "unsafe" -func VerifySp1Proof(proofBuffer []byte, proofLen uint32, elfBuffer []byte, elfLen uint32) bool { +func VerifySp1Proof(proofBuffer []byte, elfBuffer []byte) bool { if len(proofBuffer) == 0 || len(elfBuffer) == 0 { return false } @@ -17,5 +17,5 @@ func VerifySp1Proof(proofBuffer []byte, proofLen uint32, elfBuffer []byte, elfLe proofPtr := (*C.uchar)(unsafe.Pointer(&proofBuffer[0])) elfPtr := (*C.uchar)(unsafe.Pointer(&elfBuffer[0])) - return (bool)(C.verify_sp1_proof_ffi(proofPtr, (C.uint32_t)(proofLen), elfPtr, (C.uint32_t)(elfLen))) + return (bool)(C.verify_sp1_proof_ffi(proofPtr, (C.uint32_t)(len(proofBuffer)), elfPtr, (C.uint32_t)(len(elfBuffer)))) } diff --git a/operator/sp1/sp1_test.go b/operator/sp1/sp1_test.go index d1593225e..d342751bd 100644 --- a/operator/sp1/sp1_test.go +++ b/operator/sp1/sp1_test.go @@ -7,32 +7,22 @@ import ( "github.com/yetanotherco/aligned_layer/operator/sp1" ) -const MaxProofSize = 2 * 1024 * 1024 -const MaxElfSize = 2 * 1024 * 1024 +const ProofFilePath = "../../scripts/test_files/sp1/sp1_fibonacci.proof" -func TestFibonacciSp1ProofVerifies(t *testing.T) { - proofFile, err := os.Open("../../scripts/test_files/sp1/sp1_fibonacci.proof") - if err != nil { - t.Errorf("could not open proof file: %s", err) - } - proofBytes := make([]byte, MaxProofSize) - nReadProofBytes, err := proofFile.Read(proofBytes) - if err != nil { - t.Errorf("could not read bytes from file") - } +const ElfFilePath = "../../scripts/test_files/sp1/sp1_fibonacci.elf" - elfFile, err := os.Open("../../scripts/test_files/sp1/sp1_fibonacci.elf") +func TestFibonacciSp1ProofVerifies(t *testing.T) { + proofBytes, err := os.ReadFile(ProofFilePath) if err != nil { t.Errorf("could not open proof file: %s", err) } - elfBytes := make([]byte, MaxElfSize) - nReadElfBytes, err := elfFile.Read(elfBytes) + elfBytes, err := os.ReadFile(ElfFilePath) if err != nil { - t.Errorf("could not read bytes from file") + t.Errorf("could not open elf file: %s", err) } - if !sp1.VerifySp1Proof(proofBytes, uint32(nReadProofBytes), elfBytes, uint32(nReadElfBytes)) { + if !sp1.VerifySp1Proof(proofBytes, elfBytes) { t.Errorf("proof did not verify") } } diff --git a/scripts/test_files/gnark_groth16_bn254_script/groth16.proof b/scripts/test_files/gnark_groth16_bn254_script/groth16.proof index f9560b7d4..88f395648 100644 Binary files a/scripts/test_files/gnark_groth16_bn254_script/groth16.proof and b/scripts/test_files/gnark_groth16_bn254_script/groth16.proof differ diff --git a/scripts/test_files/gnark_groth16_bn254_script/groth16.vk b/scripts/test_files/gnark_groth16_bn254_script/groth16.vk index bc3870dcd..aac63459b 100644 Binary files a/scripts/test_files/gnark_groth16_bn254_script/groth16.vk and b/scripts/test_files/gnark_groth16_bn254_script/groth16.vk differ