From 697f6b65ecfae57061539d3525937f90d1d95d36 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 9 Oct 2023 16:26:39 -0700 Subject: [PATCH 01/19] feat: rustx + refactor plonky2x --- plonky2x/.env.example => .env.example | 0 .gitignore | 1 - .goreleaser.yml | 163 ------- .vscode/settings.json | 4 +- Cargo.lock | 450 +++++++++++++++++- Cargo.toml | 2 +- Dockerfile.release | 6 - cli/assets/circuit.tmpl | 46 -- cli/assets/embed.go | 12 - cli/assets/main.tmpl | 10 - cli/cmd/build.go | 57 --- cli/cmd/fixture.go | 59 --- cli/cmd/init.go | 139 ------ cli/cmd/input.go | 31 -- cli/cmd/prove.go | 59 --- cli/cmd/root.go | 22 - cli/config/config.go | 34 -- cli/main.go | 9 - cli/utils/abi/encode.go | 85 ---- cli/utils/abi/encode_test.go | 95 ---- gnarkx/succinct/circuit_test.go | 13 + plonky2x/.gitignore | 5 - plonky2x/README.md | 9 - plonky2x/{ => core}/Cargo.toml | 2 +- plonky2x/{ => core}/examples/evm.json | 0 plonky2x/{ => core}/examples/evm.rs | 4 +- plonky2x/{ => core}/examples/field.json | 0 plonky2x/{ => core}/examples/field.rs | 4 +- .../{ => core}/examples/mapreduce_balances.rs | 4 +- .../examples/mapreduce_validators.rs | 4 +- .../{ => core}/src/backend/circuit/build.rs | 0 .../{ => core}/src/backend/circuit/config.rs | 5 +- .../{ => core}/src/backend/circuit/input.rs | 0 .../{ => core}/src/backend/circuit/mock.rs | 0 .../{ => core}/src/backend/circuit/mod.rs | 2 +- .../{ => core}/src/backend/circuit/output.rs | 0 .../backend/circuit/serialization/gates.rs | 0 .../backend/circuit/serialization/hints.rs | 0 .../src/backend/circuit/serialization/mod.rs | 0 .../backend/circuit/serialization/registry.rs | 0 .../{ => core}/src/backend/circuit/witness.rs | 0 .../src/backend/function/args.rs} | 25 +- .../{ => core}/src/backend/function/mod.rs | 136 ++---- .../src/backend/function/request.rs | 0 .../{ => core}/src/backend/function/result.rs | 0 plonky2x/{ => core}/src/backend/mod.rs | 0 plonky2x/{ => core}/src/backend/prover/env.rs | 0 .../{ => core}/src/backend/prover/local.rs | 0 plonky2x/{ => core}/src/backend/prover/mod.rs | 0 .../{ => core}/src/backend/prover/remote.rs | 0 .../{ => core}/src/backend/prover/service.rs | 0 .../{ => core}/src/backend/wrapper/mod.rs | 0 .../src/backend/wrapper/plonky2_config.rs | 0 .../src/backend/wrapper/poseidon_bn128.rs | 0 .../wrapper/poseidon_bn128_constants.rs | 0 .../{ => core}/src/backend/wrapper/utils.rs | 0 .../{ => core}/src/backend/wrapper/wrap.rs | 4 +- .../src/frontend/builder/boolean.rs | 0 .../{ => core}/src/frontend/builder/io.rs | 0 .../{ => core}/src/frontend/builder/mod.rs | 0 .../{ => core}/src/frontend/builder/proof.rs | 0 .../{ => core}/src/frontend/builder/watch.rs | 0 .../{ => core}/src/frontend/curta/builder.rs | 0 .../src/frontend/curta/ec/aggregate/air.rs | 0 .../frontend/curta/ec/aggregate/builder.rs | 0 .../src/frontend/curta/ec/aggregate/hint.rs | 0 .../src/frontend/curta/ec/aggregate/mod.rs | 0 .../{ => core}/src/frontend/curta/ec/mod.rs | 0 .../{ => core}/src/frontend/curta/ec/point.rs | 0 .../src/frontend/curta/field/mod.rs | 0 .../src/frontend/curta/field/variable.rs | 0 .../{ => core}/src/frontend/curta/hash/mod.rs | 0 .../src/frontend/curta/hash/sha/mod.rs | 0 .../frontend/curta/hash/sha/sha256/builder.rs | 0 .../frontend/curta/hash/sha/sha256/hint.rs | 0 .../src/frontend/curta/hash/sha/sha256/mod.rs | 0 plonky2x/{ => core}/src/frontend/curta/mod.rs | 0 .../{ => core}/src/frontend/curta/proof.rs | 0 .../frontend/ecc/ed25519/curve/curve_adds.rs | 0 .../ecc/ed25519/curve/curve_multiplication.rs | 0 .../frontend/ecc/ed25519/curve/curve_types.rs | 0 .../src/frontend/ecc/ed25519/curve/ed25519.rs | 0 .../src/frontend/ecc/ed25519/curve/eddsa.rs | 0 .../src/frontend/ecc/ed25519/curve/mod.rs | 0 .../ecc/ed25519/field/ed25519_base.rs | 0 .../ecc/ed25519/field/ed25519_scalar.rs | 0 .../ecc/ed25519/field/field_testing.rs | 0 .../src/frontend/ecc/ed25519/field/mod.rs | 0 .../src/frontend/ecc/ed25519/gadgets/curve.rs | 0 .../src/frontend/ecc/ed25519/gadgets/eddsa.rs | 0 .../src/frontend/ecc/ed25519/gadgets/mod.rs | 0 .../frontend/ecc/ed25519/gadgets/verify.rs | 0 .../src/frontend/ecc/ed25519/mod.rs | 0 plonky2x/{ => core}/src/frontend/ecc/mod.rs | 0 .../src/frontend/eth/beacon/builder.rs | 0 .../eth/beacon/generators/all_withdrawals.rs | 0 .../frontend/eth/beacon/generators/balance.rs | 0 .../eth/beacon/generators/balance_witness.rs | 0 .../eth/beacon/generators/balances.rs | 0 .../eth/beacon/generators/eth1_block.rs | 0 .../frontend/eth/beacon/generators/header.rs | 0 .../eth/beacon/generators/historical.rs | 0 .../src/frontend/eth/beacon/generators/mod.rs | 0 .../eth/beacon/generators/partial_balances.rs | 0 .../beacon/generators/partial_validators.rs | 0 .../eth/beacon/generators/validator.rs | 0 .../beacon/generators/validator_witness.rs | 0 .../eth/beacon/generators/validators.rs | 0 .../eth/beacon/generators/withdrawal.rs | 0 .../eth/beacon/generators/withdrawals.rs | 0 .../{ => core}/src/frontend/eth/beacon/mod.rs | 0 .../src/frontend/eth/beacon/vars/balances.rs | 0 .../eth/beacon/vars/compressed_validator.rs | 0 .../src/frontend/eth/beacon/vars/header.rs | 0 .../src/frontend/eth/beacon/vars/mod.rs | 0 .../src/frontend/eth/beacon/vars/validator.rs | 0 .../frontend/eth/beacon/vars/validators.rs | 0 .../frontend/eth/beacon/vars/withdrawal.rs | 0 .../frontend/eth/beacon/vars/withdrawals.rs | 0 plonky2x/{ => core}/src/frontend/eth/mod.rs | 0 .../src/frontend/eth/mpt/builder.rs | 0 .../frontend/eth/mpt/fixtures/example.json | 0 .../src/frontend/eth/mpt/generators.rs | 0 .../{ => core}/src/frontend/eth/mpt/mod.rs | 0 .../src/frontend/eth/mpt/reference.rs | 0 .../{ => core}/src/frontend/eth/mpt/rlc.rs | 0 .../{ => core}/src/frontend/eth/mpt/utils.rs | 0 .../src/frontend/eth/rlp/builder.rs | 0 .../{ => core}/src/frontend/eth/rlp/mod.rs | 0 .../src/frontend/eth/storage/builder.rs | 0 .../frontend/eth/storage/generators/block.rs | 0 .../frontend/eth/storage/generators/mod.rs | 0 .../eth/storage/generators/storage.rs | 0 .../src/frontend/eth/storage/mod.rs | 0 .../src/frontend/eth/storage/utils.rs | 0 .../src/frontend/eth/storage/vars/block.rs | 0 .../src/frontend/eth/storage/vars/mod.rs | 0 .../src/frontend/eth/storage/vars/storage.rs | 0 plonky2x/{ => core}/src/frontend/eth/utils.rs | 0 plonky2x/{ => core}/src/frontend/eth/vars.rs | 0 .../src/frontend/hash/bit_operations/mod.rs | 0 .../src/frontend/hash/bit_operations/u8.rs | 0 .../src/frontend/hash/bit_operations/util.rs | 0 .../src/frontend/hash/blake2/blake2b.rs | 0 .../src/frontend/hash/blake2/blake2b_curta.rs | 0 .../src/frontend/hash/blake2/mod.rs | 0 .../src/frontend/hash/keccak/keccak256.rs | 0 .../src/frontend/hash/keccak/mod.rs | 0 plonky2x/{ => core}/src/frontend/hash/mod.rs | 0 .../src/frontend/hash/poseidon/mod.rs | 0 .../src/frontend/hash/poseidon/poseidon256.rs | 0 .../{ => core}/src/frontend/hash/sha/mod.rs | 0 .../src/frontend/hash/sha/sha256.rs | 0 .../src/frontend/hash/sha/sha256_curta.rs | 0 .../src/frontend/hash/sha/sha512.rs | 0 .../src/frontend/hint/asynchronous/builder.rs | 0 .../src/frontend/hint/asynchronous/channel.rs | 0 .../frontend/hint/asynchronous/generator.rs | 0 .../src/frontend/hint/asynchronous/handler.rs | 0 .../src/frontend/hint/asynchronous/hint.rs | 0 .../src/frontend/hint/asynchronous/mod.rs | 0 .../frontend/hint/asynchronous/serializer.rs | 0 plonky2x/{ => core}/src/frontend/hint/mod.rs | 0 .../src/frontend/hint/simple/generator.rs | 0 .../src/frontend/hint/simple/hint.rs | 0 .../src/frontend/hint/simple/mod.rs | 0 .../src/frontend/hint/simple/serializer.rs | 0 .../src/frontend/hint/synchronous.rs | 0 .../src/frontend/mapreduce/generator.rs | 0 .../{ => core}/src/frontend/mapreduce/mod.rs | 0 .../{ => core}/src/frontend/merkle/mod.rs | 0 .../src/frontend/merkle/tendermint.rs | 0 .../{ => core}/src/frontend/merkle/tree.rs | 0 plonky2x/{ => core}/src/frontend/mod.rs | 0 .../src/frontend/num/biguint/mod.rs | 0 plonky2x/{ => core}/src/frontend/num/mod.rs | 0 .../src/frontend/num/nonnative/mod.rs | 0 .../src/frontend/num/nonnative/nonnative.rs | 0 .../frontend/num/nonnative/split_nonnative.rs | 0 .../num/u32/gadgets/arithmetic_u32.rs | 0 .../src/frontend/num/u32/gadgets/mod.rs | 0 .../num/u32/gadgets/multiple_comparison.rs | 0 .../frontend/num/u32/gadgets/range_check.rs | 0 .../frontend/num/u32/gates/add_many_u32.rs | 0 .../frontend/num/u32/gates/arithmetic_u32.rs | 0 .../src/frontend/num/u32/gates/comparison.rs | 0 .../src/frontend/num/u32/gates/mod.rs | 0 .../frontend/num/u32/gates/range_check_u32.rs | 0 .../frontend/num/u32/gates/subtraction_u32.rs | 0 .../{ => core}/src/frontend/num/u32/mod.rs | 0 .../src/frontend/num/u32/serialization.rs | 0 .../src/frontend/num/u32/witness.rs | 0 .../{ => core}/src/frontend/ops/bitwise.rs | 0 plonky2x/{ => core}/src/frontend/ops/index.rs | 0 plonky2x/{ => core}/src/frontend/ops/math.rs | 0 plonky2x/{ => core}/src/frontend/ops/mod.rs | 0 .../src/frontend/recursion/extension.rs | 0 .../src/frontend/recursion/fri/mod.rs | 0 .../src/frontend/recursion/fri/proof.rs | 0 .../{ => core}/src/frontend/recursion/hash.rs | 0 .../{ => core}/src/frontend/recursion/mod.rs | 0 .../src/frontend/recursion/polynomial.rs | 0 plonky2x/{ => core}/src/frontend/uint/mod.rs | 0 .../{ => core}/src/frontend/uint/uint128.rs | 0 .../{ => core}/src/frontend/uint/uint256.rs | 0 .../{ => core}/src/frontend/uint/uint32.rs | 0 .../{ => core}/src/frontend/uint/uint32_n.rs | 0 .../{ => core}/src/frontend/uint/uint64.rs | 0 .../{ => core}/src/frontend/vars/array.rs | 0 .../{ => core}/src/frontend/vars/boolean.rs | 0 plonky2x/{ => core}/src/frontend/vars/byte.rs | 0 .../{ => core}/src/frontend/vars/bytes.rs | 0 .../{ => core}/src/frontend/vars/bytes32.rs | 0 .../src/frontend/vars/collections.rs | 0 plonky2x/{ => core}/src/frontend/vars/mod.rs | 0 .../{ => core}/src/frontend/vars/stream.rs | 0 .../{ => core}/src/frontend/vars/variable.rs | 0 plonky2x/{ => core}/src/lib.rs | 0 .../{ => core}/src/resources/Verifier.sol | 0 .../{ => core}/src/utils/eth/beacon/mod.rs | 0 .../src/utils/eth/beaconchain/mod.rs | 0 plonky2x/{ => core}/src/utils/eth/mod.rs | 0 plonky2x/{ => core}/src/utils/hash/mod.rs | 0 plonky2x/{ => core}/src/utils/lido/mod.rs | 0 .../src/utils/lido/node_operators_abi.json | 0 plonky2x/{ => core}/src/utils/lido/utils.rs | 0 plonky2x/{ => core}/src/utils/mod.rs | 0 plonky2x/{ => core}/src/utils/poseidon/mod.rs | 0 plonky2x/{ => core}/src/utils/proof/mod.rs | 0 plonky2x/{ => core}/src/utils/reqwest/mod.rs | 0 plonky2x/{ => core}/src/utils/serde/mod.rs | 0 plonky2x/{ => core}/src/utils/stream.rs | 0 .../derive}/Cargo.toml | 0 .../derive}/src/assert_is_valid.rs | 0 .../derive}/src/constant.rs | 0 .../derive}/src/elements.rs | 0 .../derive}/src/init.rs | 0 .../derive}/src/lib.rs | 0 .../derive}/src/value.rs | 0 .../derive}/src/variables.rs | 0 .../derive}/src/witness.rs | 0 .../verifier}/circuit.go | 0 .../verifier}/cli.go | 0 .../verifier}/prover.go | 0 .../verifier}/verifier.go | 0 .../verifier}/verifier_test.go | 0 rustx/Cargo.toml | 33 ++ rustx/examples/eth_call.rs | 86 ++++ rustx/src/args.rs | 31 ++ rustx/src/function.rs | 96 ++++ rustx/src/lib.rs | 3 + rustx/src/program.rs | 13 + scripts/abi.sh | 14 - scripts/binding.sh | 18 - scripts/release.sh | 20 - succinctup/README.md | 73 --- succinctup/install | 65 --- succinctup/succinctup | 322 ------------- 258 files changed, 783 insertions(+), 1492 deletions(-) rename plonky2x/.env.example => .env.example (100%) delete mode 100755 .goreleaser.yml delete mode 100644 Dockerfile.release delete mode 100644 cli/assets/circuit.tmpl delete mode 100644 cli/assets/embed.go delete mode 100644 cli/assets/main.tmpl delete mode 100644 cli/cmd/build.go delete mode 100644 cli/cmd/fixture.go delete mode 100644 cli/cmd/init.go delete mode 100644 cli/cmd/input.go delete mode 100644 cli/cmd/prove.go delete mode 100644 cli/cmd/root.go delete mode 100644 cli/config/config.go delete mode 100644 cli/main.go delete mode 100644 cli/utils/abi/encode.go delete mode 100644 cli/utils/abi/encode_test.go delete mode 100644 plonky2x/.gitignore delete mode 100644 plonky2x/README.md rename plonky2x/{ => core}/Cargo.toml (97%) rename plonky2x/{ => core}/examples/evm.json (100%) rename plonky2x/{ => core}/examples/evm.rs (94%) rename plonky2x/{ => core}/examples/field.json (100%) rename plonky2x/{ => core}/examples/field.rs (94%) rename plonky2x/{ => core}/examples/mapreduce_balances.rs (97%) rename plonky2x/{ => core}/examples/mapreduce_validators.rs (98%) rename plonky2x/{ => core}/src/backend/circuit/build.rs (100%) rename plonky2x/{ => core}/src/backend/circuit/config.rs (90%) rename plonky2x/{ => core}/src/backend/circuit/input.rs (100%) rename plonky2x/{ => core}/src/backend/circuit/mock.rs (100%) rename plonky2x/{ => core}/src/backend/circuit/mod.rs (96%) rename plonky2x/{ => core}/src/backend/circuit/output.rs (100%) rename plonky2x/{ => core}/src/backend/circuit/serialization/gates.rs (100%) rename plonky2x/{ => core}/src/backend/circuit/serialization/hints.rs (100%) rename plonky2x/{ => core}/src/backend/circuit/serialization/mod.rs (100%) rename plonky2x/{ => core}/src/backend/circuit/serialization/registry.rs (100%) rename plonky2x/{ => core}/src/backend/circuit/witness.rs (100%) rename plonky2x/{src/backend/function/cli.rs => core/src/backend/function/args.rs} (65%) rename plonky2x/{ => core}/src/backend/function/mod.rs (71%) rename plonky2x/{ => core}/src/backend/function/request.rs (100%) rename plonky2x/{ => core}/src/backend/function/result.rs (100%) rename plonky2x/{ => core}/src/backend/mod.rs (100%) rename plonky2x/{ => core}/src/backend/prover/env.rs (100%) rename plonky2x/{ => core}/src/backend/prover/local.rs (100%) rename plonky2x/{ => core}/src/backend/prover/mod.rs (100%) rename plonky2x/{ => core}/src/backend/prover/remote.rs (100%) rename plonky2x/{ => core}/src/backend/prover/service.rs (100%) rename plonky2x/{ => core}/src/backend/wrapper/mod.rs (100%) rename plonky2x/{ => core}/src/backend/wrapper/plonky2_config.rs (100%) rename plonky2x/{ => core}/src/backend/wrapper/poseidon_bn128.rs (100%) rename plonky2x/{ => core}/src/backend/wrapper/poseidon_bn128_constants.rs (100%) rename plonky2x/{ => core}/src/backend/wrapper/utils.rs (100%) rename plonky2x/{ => core}/src/backend/wrapper/wrap.rs (99%) rename plonky2x/{ => core}/src/frontend/builder/boolean.rs (100%) rename plonky2x/{ => core}/src/frontend/builder/io.rs (100%) rename plonky2x/{ => core}/src/frontend/builder/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/builder/proof.rs (100%) rename plonky2x/{ => core}/src/frontend/builder/watch.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/builder.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/ec/aggregate/air.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/ec/aggregate/builder.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/ec/aggregate/hint.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/ec/aggregate/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/ec/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/ec/point.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/field/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/field/variable.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/hash/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/hash/sha/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/hash/sha/sha256/builder.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/hash/sha/sha256/hint.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/hash/sha/sha256/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/curta/proof.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/curve/curve_adds.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/curve/curve_multiplication.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/curve/curve_types.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/curve/ed25519.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/curve/eddsa.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/curve/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/field/ed25519_base.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/field/ed25519_scalar.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/field/field_testing.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/field/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/gadgets/curve.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/gadgets/eddsa.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/gadgets/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/gadgets/verify.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/ed25519/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/ecc/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/builder.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/all_withdrawals.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/balance.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/balance_witness.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/balances.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/eth1_block.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/header.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/historical.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/partial_balances.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/partial_validators.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/validator.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/validator_witness.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/validators.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/withdrawal.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/generators/withdrawals.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/vars/balances.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/vars/compressed_validator.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/vars/header.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/vars/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/vars/validator.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/vars/validators.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/vars/withdrawal.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/beacon/vars/withdrawals.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/mpt/builder.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/mpt/fixtures/example.json (100%) rename plonky2x/{ => core}/src/frontend/eth/mpt/generators.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/mpt/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/mpt/reference.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/mpt/rlc.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/mpt/utils.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/rlp/builder.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/rlp/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/storage/builder.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/storage/generators/block.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/storage/generators/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/storage/generators/storage.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/storage/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/storage/utils.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/storage/vars/block.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/storage/vars/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/storage/vars/storage.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/utils.rs (100%) rename plonky2x/{ => core}/src/frontend/eth/vars.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/bit_operations/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/bit_operations/u8.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/bit_operations/util.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/blake2/blake2b.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/blake2/blake2b_curta.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/blake2/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/keccak/keccak256.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/keccak/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/poseidon/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/poseidon/poseidon256.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/sha/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/sha/sha256.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/sha/sha256_curta.rs (100%) rename plonky2x/{ => core}/src/frontend/hash/sha/sha512.rs (100%) rename plonky2x/{ => core}/src/frontend/hint/asynchronous/builder.rs (100%) rename plonky2x/{ => core}/src/frontend/hint/asynchronous/channel.rs (100%) rename plonky2x/{ => core}/src/frontend/hint/asynchronous/generator.rs (100%) rename plonky2x/{ => core}/src/frontend/hint/asynchronous/handler.rs (100%) rename plonky2x/{ => core}/src/frontend/hint/asynchronous/hint.rs (100%) rename plonky2x/{ => core}/src/frontend/hint/asynchronous/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/hint/asynchronous/serializer.rs (100%) rename plonky2x/{ => core}/src/frontend/hint/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/hint/simple/generator.rs (100%) rename plonky2x/{ => core}/src/frontend/hint/simple/hint.rs (100%) rename plonky2x/{ => core}/src/frontend/hint/simple/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/hint/simple/serializer.rs (100%) rename plonky2x/{ => core}/src/frontend/hint/synchronous.rs (100%) rename plonky2x/{ => core}/src/frontend/mapreduce/generator.rs (100%) rename plonky2x/{ => core}/src/frontend/mapreduce/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/merkle/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/merkle/tendermint.rs (100%) rename plonky2x/{ => core}/src/frontend/merkle/tree.rs (100%) rename plonky2x/{ => core}/src/frontend/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/num/biguint/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/num/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/num/nonnative/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/num/nonnative/nonnative.rs (100%) rename plonky2x/{ => core}/src/frontend/num/nonnative/split_nonnative.rs (100%) rename plonky2x/{ => core}/src/frontend/num/u32/gadgets/arithmetic_u32.rs (100%) rename plonky2x/{ => core}/src/frontend/num/u32/gadgets/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/num/u32/gadgets/multiple_comparison.rs (100%) rename plonky2x/{ => core}/src/frontend/num/u32/gadgets/range_check.rs (100%) rename plonky2x/{ => core}/src/frontend/num/u32/gates/add_many_u32.rs (100%) rename plonky2x/{ => core}/src/frontend/num/u32/gates/arithmetic_u32.rs (100%) rename plonky2x/{ => core}/src/frontend/num/u32/gates/comparison.rs (100%) rename plonky2x/{ => core}/src/frontend/num/u32/gates/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/num/u32/gates/range_check_u32.rs (100%) rename plonky2x/{ => core}/src/frontend/num/u32/gates/subtraction_u32.rs (100%) rename plonky2x/{ => core}/src/frontend/num/u32/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/num/u32/serialization.rs (100%) rename plonky2x/{ => core}/src/frontend/num/u32/witness.rs (100%) rename plonky2x/{ => core}/src/frontend/ops/bitwise.rs (100%) rename plonky2x/{ => core}/src/frontend/ops/index.rs (100%) rename plonky2x/{ => core}/src/frontend/ops/math.rs (100%) rename plonky2x/{ => core}/src/frontend/ops/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/recursion/extension.rs (100%) rename plonky2x/{ => core}/src/frontend/recursion/fri/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/recursion/fri/proof.rs (100%) rename plonky2x/{ => core}/src/frontend/recursion/hash.rs (100%) rename plonky2x/{ => core}/src/frontend/recursion/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/recursion/polynomial.rs (100%) rename plonky2x/{ => core}/src/frontend/uint/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/uint/uint128.rs (100%) rename plonky2x/{ => core}/src/frontend/uint/uint256.rs (100%) rename plonky2x/{ => core}/src/frontend/uint/uint32.rs (100%) rename plonky2x/{ => core}/src/frontend/uint/uint32_n.rs (100%) rename plonky2x/{ => core}/src/frontend/uint/uint64.rs (100%) rename plonky2x/{ => core}/src/frontend/vars/array.rs (100%) rename plonky2x/{ => core}/src/frontend/vars/boolean.rs (100%) rename plonky2x/{ => core}/src/frontend/vars/byte.rs (100%) rename plonky2x/{ => core}/src/frontend/vars/bytes.rs (100%) rename plonky2x/{ => core}/src/frontend/vars/bytes32.rs (100%) rename plonky2x/{ => core}/src/frontend/vars/collections.rs (100%) rename plonky2x/{ => core}/src/frontend/vars/mod.rs (100%) rename plonky2x/{ => core}/src/frontend/vars/stream.rs (100%) rename plonky2x/{ => core}/src/frontend/vars/variable.rs (100%) rename plonky2x/{ => core}/src/lib.rs (100%) rename plonky2x/{ => core}/src/resources/Verifier.sol (100%) rename plonky2x/{ => core}/src/utils/eth/beacon/mod.rs (100%) rename plonky2x/{ => core}/src/utils/eth/beaconchain/mod.rs (100%) rename plonky2x/{ => core}/src/utils/eth/mod.rs (100%) rename plonky2x/{ => core}/src/utils/hash/mod.rs (100%) rename plonky2x/{ => core}/src/utils/lido/mod.rs (100%) rename plonky2x/{ => core}/src/utils/lido/node_operators_abi.json (100%) rename plonky2x/{ => core}/src/utils/lido/utils.rs (100%) rename plonky2x/{ => core}/src/utils/mod.rs (100%) rename plonky2x/{ => core}/src/utils/poseidon/mod.rs (100%) rename plonky2x/{ => core}/src/utils/proof/mod.rs (100%) rename plonky2x/{ => core}/src/utils/reqwest/mod.rs (100%) rename plonky2x/{ => core}/src/utils/serde/mod.rs (100%) rename plonky2x/{ => core}/src/utils/stream.rs (100%) rename {plonky2x-derive => plonky2x/derive}/Cargo.toml (100%) rename {plonky2x-derive => plonky2x/derive}/src/assert_is_valid.rs (100%) rename {plonky2x-derive => plonky2x/derive}/src/constant.rs (100%) rename {plonky2x-derive => plonky2x/derive}/src/elements.rs (100%) rename {plonky2x-derive => plonky2x/derive}/src/init.rs (100%) rename {plonky2x-derive => plonky2x/derive}/src/lib.rs (100%) rename {plonky2x-derive => plonky2x/derive}/src/value.rs (100%) rename {plonky2x-derive => plonky2x/derive}/src/variables.rs (100%) rename {plonky2x-derive => plonky2x/derive}/src/witness.rs (100%) rename {plonky2x-verifier => plonky2x/verifier}/circuit.go (100%) rename {plonky2x-verifier => plonky2x/verifier}/cli.go (100%) rename {plonky2x-verifier => plonky2x/verifier}/prover.go (100%) rename {plonky2x-verifier => plonky2x/verifier}/verifier.go (100%) rename {plonky2x-verifier => plonky2x/verifier}/verifier_test.go (100%) create mode 100644 rustx/Cargo.toml create mode 100644 rustx/examples/eth_call.rs create mode 100644 rustx/src/args.rs create mode 100644 rustx/src/function.rs create mode 100644 rustx/src/lib.rs create mode 100644 rustx/src/program.rs delete mode 100644 scripts/abi.sh delete mode 100644 scripts/binding.sh delete mode 100644 scripts/release.sh delete mode 100644 succinctup/README.md delete mode 100755 succinctup/install delete mode 100755 succinctup/succinctup diff --git a/plonky2x/.env.example b/.env.example similarity index 100% rename from plonky2x/.env.example rename to .env.example diff --git a/.gitignore b/.gitignore index f8128b24e..0b574af8a 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,6 @@ keystore **/*.bin **/target **/build -!/build **/data **/__pycache__ diff --git a/.goreleaser.yml b/.goreleaser.yml deleted file mode 100755 index 37954b363..000000000 --- a/.goreleaser.yml +++ /dev/null @@ -1,163 +0,0 @@ -# Docs: https://goreleaser.com/customization/builds/ -project_name: sdk - -builds: - - id: "sdk" - binary: "sdk" - main: ./cli - env: - - GO111MODULE=on - - CGO_ENABLED=0 - goos: - - linux - - freebsd - - openbsd - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - "6" - - "7" - ldflags: - - -s - - -w - - -X main.version={{ .Version }} - - -X main.revision={{ .FullCommit }} - - -X main.buildDate={{ .Date }} - -source: - enabled: true - name_template: "{{ .ProjectName }}-{{ .Version }}" - prefix_template: "{{ .ProjectName }}-{{ .Version }}/" - -checksum: - name_template: "{{ .ProjectName }}-{{ .Version }}.sha256" - algorithm: sha256 - -# signs: -# - artifacts: checksum -# args: -# [ -# "--batch", -# "-u", -# "{{ .Env.GPG_FINGERPRINT }}", -# "--output", -# "${signature}", -# "--detach-sign", -# "${artifact}", -# ] - -docker_manifests: - - name_template: ghcr.io/succinctlabs/sdk:v{{ .Version }} - image_templates: - - ghcr.io/succinctlabs/sdk:v{{ .Version }}-amd64 - - ghcr.io/succinctlabs/sdk:v{{ .Version }}-arm64v8 - - ghcr.io/succinctlabs/sdk:v{{ .Version }}-arm32v7 - - ghcr.io/succinctlabs/sdk:v{{ .Version }}-arm32v6 - - name_template: ghcr.io/succinctlabs/sdk:v{{ .Major }}.{{ .Minor }} - image_templates: - - ghcr.io/succinctlabs/sdk:v{{ .Major }}.{{ .Minor }}-amd64 - - ghcr.io/succinctlabs/sdk:v{{ .Major }}.{{ .Minor }}-arm64v8 - - ghcr.io/succinctlabs/sdk:v{{ .Major }}.{{ .Minor }}-arm32v7 - - ghcr.io/succinctlabs/sdk:v{{ .Major }}.{{ .Minor }}-arm32v6 - - name_template: ghcr.io/succinctlabs/sdk:latest - image_templates: - - ghcr.io/succinctlabs/sdk:latest-amd64 - - ghcr.io/succinctlabs/sdk:latest-arm64v8 - - ghcr.io/succinctlabs/sdk:latest-arm32v7 - - ghcr.io/succinctlabs/sdk:latest-arm32v6 - - name_template: ghcr.io/succinctlabs/sdk:nightly - image_templates: - - ghcr.io/succinctlabs/sdk:nightly-amd64 - - ghcr.io/succinctlabs/sdk:nightly-arm64v8 - - ghcr.io/succinctlabs/sdk:nightly-arm32v7 - - ghcr.io/succinctlabs/sdk:nightly-arm32v6 - -dockers: - - image_templates: - - ghcr.io/succinctlabs/sdk:v{{ .Version }}-amd64 - - ghcr.io/succinctlabs/sdk:v{{ .Major }}.{{ .Minor }}-amd64 - - ghcr.io/succinctlabs/sdk:latest-amd64 - - ghcr.io/succinctlabs/sdk:nightly-amd64 - ids: ["sdk"] - goarch: amd64 - build_flag_templates: - - --build-arg=BINARY_NAME=sdk - - --platform=linux/amd64 - - --label=org.opencontainers.image.title=sdk - - --label=org.opencontainers.image.description=sdk - - --label=org.opencontainers.image.url=https://github.com/succinctlabs/sdk - - --label=org.opencontainers.image.source=https://github.com/succinctlabs/sdk - - --label=org.opencontainers.image.version=v{{ .Version }} - - --label=org.opencontainers.image.created={{ .Date }} - - --label=org.opencontainers.image.revision={{ .FullCommit }} - dockerfile: Dockerfile.release - use: buildx - - image_templates: - - ghcr.io/succinctlabs/sdk:v{{ .Version }}-arm64v8 - - ghcr.io/succinctlabs/sdk:v{{ .Major }}.{{ .Minor }}-arm64v8 - - ghcr.io/succinctlabs/sdk:latest-arm64v8 - - ghcr.io/succinctlabs/sdk:nightly-arm64v8 - ids: ["sdk"] - goarch: arm64 - build_flag_templates: - - --build-arg=BINARY_NAME=sdk - - --platform=linux/arm64/v8 - - --label=org.opencontainers.image.title=sdk - - --label=org.opencontainers.image.description=sdk - - --label=org.opencontainers.image.url=https://github.com/succinctlabs/sdk - - --label=org.opencontainers.image.source=https://github.com/succinctlabs/sdk - - --label=org.opencontainers.image.version=v{{ .Version }} - - --label=org.opencontainers.image.created={{ .Date }} - - --label=org.opencontainers.image.revision={{ .FullCommit }} - dockerfile: Dockerfile.release - use: buildx - - image_templates: - - ghcr.io/succinctlabs/sdk:v{{ .Version }}-arm32v7 - - ghcr.io/succinctlabs/sdk:v{{ .Major }}.{{ .Minor }}-arm32v7 - - ghcr.io/succinctlabs/sdk:latest-arm32v7 - - ghcr.io/succinctlabs/sdk:nightly-arm32v7 - ids: ["sdk"] - goarch: arm - goarm: "7" - build_flag_templates: - - --build-arg=BINARY_NAME=sdk - - --platform=linux/arm/v7 - - --label=org.opencontainers.image.title=sdk - - --label=org.opencontainers.image.description=sdk - - --label=org.opencontainers.image.url=https://github.com/succinctlabs/sdk - - --label=org.opencontainers.image.source=https://github.com/succinctlabs/sdk - - --label=org.opencontainers.image.version=v{{ .Version }} - - --label=org.opencontainers.image.created={{ .Date }} - - --label=org.opencontainers.image.revision={{ .FullCommit }} - dockerfile: Dockerfile.release - use: buildx - - image_templates: - - ghcr.io/succinctlabs/sdk:v{{ .Version }}-arm32v6 - - ghcr.io/succinctlabs/sdk:v{{ .Major }}.{{ .Minor }}-arm32v6 - - ghcr.io/succinctlabs/sdk:latest-arm32v6 - - ghcr.io/succinctlabs/sdk:nightly-arm32v6 - ids: ["sdk"] - goarch: arm - goarm: "6" - build_flag_templates: - - --build-arg=BINARY_NAME=sdk - - --platform=linux/arm/v6 - - --label=org.opencontainers.image.title=sdk - - --label=org.opencontainers.image.description=sdk - - --label=org.opencontainers.image.url=https://github.com/succinctlabs/sdk - - --label=org.opencontainers.image.source=https://github.com/succinctlabs/sdk - - --label=org.opencontainers.image.version=v{{ .Version }} - - --label=org.opencontainers.image.created={{ .Date }} - - --label=org.opencontainers.image.revision={{ .FullCommit }} - dockerfile: Dockerfile.release - use: buildx - -release: - name_template: "v{{ .Version }}" - footer: | - * * * - Having trouble? Open an [issue](https://github.com/succinctlabs/sdk/issues/new) on Github. - Other thoughts? Come participate with the community on [Twitter](https://twitter.com/succinctlabs) or [Discord](https://discord.gg/succinctlabs). diff --git a/.vscode/settings.json b/.vscode/settings.json index 278ad2896..4f37678bb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,8 +6,8 @@ }, "editor.rulers": [100], "rust-analyzer.linkedProjects": [ - "./plonky2x/Cargo.toml", - "./plonky2x-derive/Cargo.toml" + "./plonky2x/core/Cargo.toml", + "./plonky2x/derive/Cargo.toml" ], "rust-analyzer.check.overrideCommand": [ "cargo", diff --git a/Cargo.lock b/Cargo.lock index 989684b52..07f969855 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,6 +70,66 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloy-primitives" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0628ec0ba5b98b3370bb6be17b12f23bfce8ee4ad83823325a20546d9b03b78" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "hex-literal", + "itoa", + "proptest", + "rand", + "ruint", + "serde", + "tiny-keccak", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc0fac0fc16baf1f63f78b47c3d24718f3619b0714076f6a02957d808d52cbef" +dependencies = [ + "arrayvec", + "bytes", + "smol_str", +] + +[[package]] +name = "alloy-sol-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a98ad1696a2e17f010ae8e43e9f2a1e930ed176a8e3ff77acfeff6dfb07b42c" +dependencies = [ + "const-hex", + "dunce", + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.37", + "syn-solidity", + "tiny-keccak", +] + +[[package]] +name = "alloy-sol-types" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98d7107bed88e8f09f0ddcc3335622d87bfb6821f3e0c7473329fb1cfad5e015" +dependencies = [ + "alloy-primitives", + "alloy-sol-macro", + "const-hex", + "serde", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -139,6 +199,130 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint 0.4.4", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint 0.4.4", + "num-traits", + "paste", + "rustc_version 0.4.0", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint 0.4.4", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint 0.4.4", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint 0.4.4", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + [[package]] name = "array-macro" version = "2.1.5" @@ -179,7 +363,7 @@ checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" dependencies = [ "futures", "pharos", - "rustc_version", + "rustc_version 0.4.0", ] [[package]] @@ -395,7 +579,7 @@ checksum = "e7daec1a2a2129eeba1644b220b4647ec537b0b5d4bfd6876fcc5a540056b592" dependencies = [ "camino", "cargo-platform", - "semver", + "semver 1.0.19", "serde", "serde_json", "thiserror", @@ -584,6 +768,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "core-foundation" version = "0.9.3" @@ -716,7 +906,7 @@ dependencies = [ "curve25519-dalek-derive", "fiat-crypto", "platforms", - "rustc_version", + "rustc_version 0.4.0", "subtle", "zeroize", ] @@ -804,14 +994,27 @@ dependencies = [ "serde", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ + "convert_case", "proc-macro2", "quote", + "rustc_version 0.4.0", "syn 1.0.109", ] @@ -1221,7 +1424,7 @@ checksum = "0e53451ea4a8128fbce33966da71132cf9e1040dcfd2a2084fd7733ada7b2045" dependencies = [ "ethers-core", "reqwest", - "semver", + "semver 1.0.19", "serde", "serde_json", "thiserror", @@ -1330,7 +1533,7 @@ dependencies = [ "path-slash", "rayon", "regex", - "semver", + "semver 1.0.19", "serde", "serde_json", "solang-parser", @@ -1359,6 +1562,17 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + [[package]] name = "ff" version = "0.13.0" @@ -1717,6 +1931,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + [[package]] name = "hmac" version = "0.12.1" @@ -2115,6 +2335,12 @@ version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "linux-raw-sys" version = "0.4.8" @@ -2299,6 +2525,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -2488,6 +2715,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + [[package]] name = "path-slash" version = "0.2.1" @@ -2531,6 +2764,17 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +[[package]] +name = "pest" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + [[package]] name = "petgraph" version = "0.6.4" @@ -2548,7 +2792,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" dependencies = [ "futures", - "rustc_version", + "rustc_version 0.4.0", ] [[package]] @@ -2863,6 +3107,32 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proptest" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.4.0", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" version = "1.0.33" @@ -2908,6 +3178,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + [[package]] name = "rayon" version = "1.8.0" @@ -3085,6 +3364,35 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ruint" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95294d6e3a6192f3aabf91c38f56505a625aa495533442744185a36d75a790c4" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp", + "num-bigint 0.4.4", + "parity-scale-codec", + "primitive-types 0.12.1", + "proptest", + "rand", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e666a5496a0b2186dbcd0ff6106e29e093c15591bde62c20d3842007c6978a09" + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -3097,13 +3405,22 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver", + "semver 1.0.19", ] [[package]] @@ -3156,6 +3473,37 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +[[package]] +name = "rustx" +version = "0.1.0" +dependencies = [ + "alloy-primitives", + "alloy-sol-types", + "clap", + "dotenv", + "env_logger", + "ethers", + "hex", + "log", + "plonky2", + "plonky2x", + "serde", + "serde_json", + "tokio", +] + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + [[package]] name = "ryu" version = "1.0.15" @@ -3278,6 +3626,15 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.19" @@ -3287,6 +3644,15 @@ dependencies = [ "serde", ] +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + [[package]] name = "send_wrapper" version = "0.4.0" @@ -3499,6 +3865,15 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +[[package]] +name = "smol_str" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +dependencies = [ + "serde", +] + [[package]] name = "socket2" version = "0.4.9" @@ -3628,7 +4003,7 @@ dependencies = [ "hex", "once_cell", "reqwest", - "semver", + "semver 1.0.19", "serde", "serde_json", "sha2 0.10.8", @@ -3659,6 +4034,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn-solidity" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b837ef12ab88835251726eb12237655e61ec8dc8a280085d1961cdc3dfd047" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.37", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -3793,9 +4180,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.32.0" +version = "1.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" dependencies = [ "backtrace", "bytes", @@ -3984,6 +4371,12 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + [[package]] name = "uint" version = "0.9.5" @@ -3996,6 +4389,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicode-bidi" version = "0.3.13" @@ -4081,6 +4480,12 @@ dependencies = [ "serde", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "vcpkg" version = "0.2.15" @@ -4093,6 +4498,15 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.4.0" @@ -4336,7 +4750,7 @@ dependencies = [ "js-sys", "log", "pharos", - "rustc_version", + "rustc_version 0.4.0", "send_wrapper 0.6.0", "thiserror", "wasm-bindgen", @@ -4364,6 +4778,20 @@ name = "zeroize" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.37", +] [[package]] name = "zip" diff --git a/Cargo.toml b/Cargo.toml index 03d01d406..0d53d7bd5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["plonky2x", "plonky2x-derive"] +members = ["plonky2x/core", "plonky2x/derive", "rustx"] resolver = "2" [profile.release] diff --git a/Dockerfile.release b/Dockerfile.release deleted file mode 100644 index a4c882361..000000000 --- a/Dockerfile.release +++ /dev/null @@ -1,6 +0,0 @@ -FROM alpine:3.17 - -ARG BINARY_NAME - -COPY $BINARY_NAME /usr/bin/app -ENTRYPOINT ["/usr/bin/app"] \ No newline at end of file diff --git a/cli/assets/circuit.tmpl b/cli/assets/circuit.tmpl deleted file mode 100644 index e4af7b585..000000000 --- a/cli/assets/circuit.tmpl +++ /dev/null @@ -1,46 +0,0 @@ -package main - -import ( - "github.com/consensys/gnark/frontend" - "github.com/succinctlabs/sdk/gnarkx/builder" - "github.com/succinctlabs/sdk/gnarkx/vars" -) - -type Circuit struct { - InputBytes []vars.Byte - OutputBytes []vars.Byte -} - -func (circuit *Circuit) GetInputBytes() *[]vars.Byte { - return &circuit.InputBytes -} - -func (circuit *Circuit) GetOutputBytes() *[]vars.Byte { - return &circuit.OutputBytes -} - -func NewCircuit() *Circuit { - circuit := &Circuit{} - circuit.InputBytes = vars.NewBytes(32) - circuit.OutputBytes = vars.NewBytes(32) - return circuit -} - -func (circuit *Circuit) SetWitness(inputBytes []byte) { -} - -func (circuit *Circuit) Assign(inputBytes []byte) error { - vars.SetBytes(&circuit.InputBytes, inputBytes) - vars.SetBytes(&circuit.OutputBytes, make([]byte, 32)) - - return nil -} - -func (circuit *Circuit) Define(baseAPI frontend.API) error { - // Use the Succinct API. - api := builder.NewAPI(baseAPI) - - api.AddU64(vars.NewU64(), vars.NewU64()) - - return nil -} diff --git a/cli/assets/embed.go b/cli/assets/embed.go deleted file mode 100644 index 40e42aacb..000000000 --- a/cli/assets/embed.go +++ /dev/null @@ -1,12 +0,0 @@ -package assets - -import "embed" - -// To use this, add all assets inside this directory and export them via the go:embed directive. -// All of them are available to other packages as embed.FS variables. - -//go:embed circuit.tmpl -var Circuit embed.FS - -//go:embed main.tmpl -var Main embed.FS diff --git a/cli/assets/main.tmpl b/cli/assets/main.tmpl deleted file mode 100644 index ca850ad7b..000000000 --- a/cli/assets/main.tmpl +++ /dev/null @@ -1,10 +0,0 @@ -// AUTOGENERATED: DO NOT TOUCH -package main - -import ( - "github.com/succinctlabs/sdk/gnarkx/succinct" -) - -func main() { - succinct.Run(NewCircuit()) -} diff --git a/cli/cmd/build.go b/cli/cmd/build.go deleted file mode 100644 index 96a26f9d6..000000000 --- a/cli/cmd/build.go +++ /dev/null @@ -1,57 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - "os/exec" - - "github.com/spf13/cobra" -) - -var buildCmd = &cobra.Command{ - Use: "build", - Short: "Build the circuit and generate artifacts", - Run: func(cmd *cobra.Command, args []string) { - buildCLI() - }, -} - -func init() { - rootCmd.AddCommand(buildCmd) -} - -func buildCLI() { - // Check for existence of initialized project - if !isProjectInitialized() { - fmt.Println("Project not initialized. Please run 'succinct init' first.") - return - } - - // Build and run the generated main.go file - if err := buildCircuit(); err != nil { - fmt.Printf("Failed to build and run the project: %v\n", err) - return - } - - fmt.Println("Circuit built and artifacts have been successfully generated.") -} - -func isProjectInitialized() bool { - // Check for specific files or directories that indicate the project is initialized - if _, err := os.Stat("circuit/main.go"); os.IsNotExist(err) { - return false - } - return true -} - -func buildCircuit() error { - args := []string{"run", "./circuit"} - buildCmd := exec.Command("go", args...) - buildCmd.Stdout = os.Stdout - buildCmd.Stderr = os.Stderr - if err := buildCmd.Run(); err != nil { - return fmt.Errorf("failed to build the circuit: %w", err) - } - - return nil -} diff --git a/cli/cmd/fixture.go b/cli/cmd/fixture.go deleted file mode 100644 index efb755e5a..000000000 --- a/cli/cmd/fixture.go +++ /dev/null @@ -1,59 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - "os/exec" - - "github.com/spf13/cobra" -) - -var fixtureCmd = &cobra.Command{ - Use: "fixture", - Short: "Generate a fixture for the circuit", - Run: func(cmd *cobra.Command, args []string) { - fixtureCLI() - }, -} - -func init() { - fixtureCmd.Flags().StringVarP(&inputBytes, "input", "i", "", "input bytes to fixture with 0x prefix") - fixtureCmd.Flags().StringVarP(&inputABI, "abi", "a", "", "ABI signature of the input types, e.g. \"(uint256,address,uint8,bool,string)\"") - fixtureCmd.Flags().StringVarP(&inputValues, "values", "v", "", "comma-separated values corresponding to the types in the ABI signature") - rootCmd.AddCommand(fixtureCmd) -} - -func fixtureCLI() { - // Check for existence of initialized project - if !isProjectInitialized() { - fmt.Println("Project not initialized. Please run 'succinct init' first.") - return - } - - input, err := parseInput(inputBytes, inputABI, inputValues) - if err != nil { - fmt.Printf("Failed to parse input: %v\n", err) - return - } - - // Prove the circuit - if err := generateFixture(input); err != nil { - fmt.Printf("Failed to generate fixture for the circuit: %v\n", err) - return - } - - fmt.Println("Generated fixture successfully.") -} - -// Run the generated main.go file with the --fixture flag and input bytes -func generateFixture(input string) error { - args := []string{"run", "./circuit", "--fixture", "--input", input} - fixtureCmd := exec.Command("go", args...) - fixtureCmd.Stdout = os.Stdout - fixtureCmd.Stderr = os.Stderr - if err := fixtureCmd.Run(); err != nil { - return fmt.Errorf("failed to run fixture generation: %w", err) - } - - return nil -} diff --git a/cli/cmd/init.go b/cli/cmd/init.go deleted file mode 100644 index 1ab226363..000000000 --- a/cli/cmd/init.go +++ /dev/null @@ -1,139 +0,0 @@ -package cmd - -import ( - "encoding/json" - "fmt" - "os" - "os/exec" - "text/template" - - "github.com/spf13/cobra" - "github.com/succinctlabs/sdk/cli/assets" - "github.com/succinctlabs/sdk/cli/config" -) - -var initCmd = &cobra.Command{ - Use: "init [--gomodule ] [--dir ]", - Short: "Initialize a new succinct project. Preset must be one of: " + fmt.Sprint(config.AllPresets), - Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { - preset := args[0] - if _, ok := config.DefaultConfigs[config.PresetType(preset)]; !ok { - fmt.Printf("Preset must be one of: %v\n", config.AllPresets) - return - } - initCLI(config.PresetType(preset)) - }, -} - -var dirName *string -var moduleName *string - -func init() { - moduleName = initCmd.Flags().StringP("gomodule", "g", "", "Go module name (ex. github.com/succinctlabs/myproject)") - dirName = initCmd.Flags().StringP("dir", "d", "circuit", "Directory to create the circuit source files in") - rootCmd.AddCommand(initCmd) -} - -func initCLI(preset config.PresetType) { - circuit, err := template.ParseFS(assets.Circuit, "circuit.tmpl") - if err != nil { - panic(err) - } - - main, err := template.ParseFS(assets.Main, "main.tmpl") - if err != nil { - panic(err) - } - - err = os.MkdirAll(*dirName, 0755) - if err != nil { - panic(err) - } - - // Create or overwrite main.go in current directory - circuitFile, err := os.Create(*dirName + "/circuit.go") - if err != nil { - panic(err) - } - defer circuitFile.Close() - - mainFile, err := os.Create(*dirName + "/main.go") - if err != nil { - panic(err) - } - defer mainFile.Close() - - err = circuit.Execute(circuitFile, nil) - if err != nil { - panic(err) - } - - err = main.Execute(mainFile, nil) - if err != nil { - panic(err) - } - - jsonFile, err := os.Create("succinct.json") - if err != nil { - panic(err) - } - defer jsonFile.Close() - - // TODO: read cli arg for preset - configContent := config.DefaultConfigs[preset] - encoder := json.NewEncoder(jsonFile) - encoder.SetIndent("", " ") - encoder.SetEscapeHTML(false) - err = encoder.Encode(configContent) - - if err := initGoModule(); err != nil { - panic(err) - } - - if err := getGoModule("github.com/consensys/gnark@develop"); err != nil { - panic(err) - } - - if err := tidyGoModule(); err != nil { - panic(err) - } - - fmt.Println("Scaffold files have been successfully generated.") -} - -// Initialize a new Go module in the project directory -func initGoModule() error { - // Check if go.mod already exists - if _, err := os.Stat("go.mod"); err == nil { - fmt.Println("go.mod already exists, adding package to existing module") - return nil - } - - cmd := exec.Command("go", "mod", "init", *moduleName) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - return cmd.Run() -} - -// Run 'go mod tidy' to set up dependencies -func tidyGoModule() error { - // Check if go.mod already exists - if _, err := os.Stat("go.mod"); err != nil { - fmt.Println("go.mod doesn't exists, skipping tidy") - return nil - } - - cmd := exec.Command("go", "mod", "tidy") - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - return cmd.Run() -} - -// Runs 'go get ' to add a dependency to the project -func getGoModule(module string) error { - cmd := exec.Command("go", "get", module) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - return cmd.Run() -} diff --git a/cli/cmd/input.go b/cli/cmd/input.go deleted file mode 100644 index ce1979b31..000000000 --- a/cli/cmd/input.go +++ /dev/null @@ -1,31 +0,0 @@ -package cmd - -import ( - "fmt" - "strings" - - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/succinctlabs/sdk/cli/utils/abi" -) - -var ( - inputBytes string - inputABI string - inputValues string -) - -// Parse the input bytes from the CLI flags -func parseInput(inputBytes string, inputABI string, inputValues string) (string, error) { - if inputBytes != "" { - return inputBytes, nil - } else if inputABI != "" && inputValues != "" { - values := strings.Split(inputValues, ",") - input, err := abi.EncodePacked(inputABI, values) - if err != nil { - return "", fmt.Errorf("error encoding input values: %w", err) - } - return hexutil.Encode(input), nil - } else { - return "", fmt.Errorf("must provide either input bytes, or input signature + values") - } -} diff --git a/cli/cmd/prove.go b/cli/cmd/prove.go deleted file mode 100644 index e83bbc278..000000000 --- a/cli/cmd/prove.go +++ /dev/null @@ -1,59 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - "os/exec" - - "github.com/spf13/cobra" -) - -var proveCmd = &cobra.Command{ - Use: "prove", - Short: "Generate a proof for the circuit", - Run: func(cmd *cobra.Command, args []string) { - proveCLI() - }, -} - -func init() { - proveCmd.Flags().StringVarP(&inputBytes, "input", "i", "", "input bytes to prove with 0x prefix") - proveCmd.Flags().StringVarP(&inputABI, "abi", "a", "", "ABI signature of the input types, e.g. \"(uint256,address,uint8,bool,string)\"") - proveCmd.Flags().StringVarP(&inputValues, "values", "v", "", "comma-separated values corresponding to the types in the ABI signature") - rootCmd.AddCommand(proveCmd) -} - -func proveCLI() { - // Check for existence of initialized project - if !isProjectInitialized() { - fmt.Println("Project not initialized. Please run 'succinct init' first.") - return - } - - input, err := parseInput(inputBytes, inputABI, inputValues) - if err != nil { - fmt.Printf("Failed to parse input: %v\n", err) - return - } - - // Prove the circuit - if err := proveCircuit(input); err != nil { - fmt.Printf("Failed to generate a proof for the circuit: %v\n", err) - return - } - - fmt.Println("Proof generated successfully.") -} - -// Run the generated main.go file with the --prove flag and input bytes -func proveCircuit(input string) error { - args := []string{"run", "./circuit", "--prove", "--input", input} - proveCmd := exec.Command("go", args...) - proveCmd.Stdout = os.Stdout - proveCmd.Stderr = os.Stderr - if err := proveCmd.Run(); err != nil { - return fmt.Errorf("failed to run proof generation: %w", err) - } - - return nil -} diff --git a/cli/cmd/root.go b/cli/cmd/root.go deleted file mode 100644 index 76fb05720..000000000 --- a/cli/cmd/root.go +++ /dev/null @@ -1,22 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - - "github.com/spf13/cobra" -) - -var rootCmd = &cobra.Command{ - Use: "succinct ", - Short: "The Succinct command line interface, used for creating and managing projects.", -} - -// Execute adds all child commands to the root command and sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the rootCmd. -func Execute() { - if err := rootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } -} diff --git a/cli/config/config.go b/cli/config/config.go deleted file mode 100644 index a3e4b3fb3..000000000 --- a/cli/config/config.go +++ /dev/null @@ -1,34 +0,0 @@ -package config - -type PresetType string - -const ( - PresetTypeGnark PresetType = "gnark" - PresetTypePlonky2 PresetType = "plonky2" - PresetTypeCircom PresetType = "circom" - PresetTypeHalo2 PresetType = "halo2" -) - -var AllPresets = []PresetType{ - PresetTypeGnark, - // PresetTypePlonky2, - // PresetTypeCircom, - // PresetTypeHalo2, -} - -type SuccinctConfig struct { - Preset PresetType `json:"preset"` - BuildCommand string `json:"build_command"` - ProveCommand string `json:"prove_command"` -} - -var GnarkConfig = SuccinctConfig{ - Preset: PresetTypeGnark, - BuildCommand: "go build -o build/main ./circuit/ && ./build/main", - ProveCommand: "./build/main -prove -input $INPUT", -} - -// TODO: make default config for each preset -var DefaultConfigs = map[PresetType]SuccinctConfig{ - PresetTypeGnark: GnarkConfig, -} diff --git a/cli/main.go b/cli/main.go deleted file mode 100644 index 473990a4f..000000000 --- a/cli/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "github.com/succinctlabs/sdk/cli/cmd" -) - -func main() { - cmd.Execute() -} diff --git a/cli/utils/abi/encode.go b/cli/utils/abi/encode.go deleted file mode 100644 index d07bdb7e1..000000000 --- a/cli/utils/abi/encode.go +++ /dev/null @@ -1,85 +0,0 @@ -package abi - -import ( - "bytes" - "encoding/binary" - "fmt" - "math/big" - "strings" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -// Emulates Solidity's abi.encodePacked() function. Must give the type signature and the type values. -// The type signature must be in the form of "(,,...)". -// The type values must be in the form of ["", "", ...]. -func EncodePacked(signature string, values []string) ([]byte, error) { - if signature == "()" { - if len(values) != 0 { - return nil, fmt.Errorf("mismatch in number of types and values") - } - return []byte{}, nil - } - - types := strings.Split(signature[1:len(signature)-1], ",") - if len(types) != len(values) { - return nil, fmt.Errorf("mismatch in number of types and values") - } - - var buffer bytes.Buffer - for i, t := range types { - switch t { - case "bytes32": - bytesVal, err := hexutil.Decode(values[i]) - if err != nil || len(bytesVal) != 32 { - return nil, fmt.Errorf("invalid bytes32 value: %s", values[i]) - } - buffer.Write(bytesVal) - case "uint256": - val := big.NewInt(0) - val.SetString(values[i], 10) - binary.Write(&buffer, binary.BigEndian, common.LeftPadBytes(val.Bytes(), 32)) - case "uint160": - val := big.NewInt(0) - val.SetString(values[i], 10) - binary.Write(&buffer, binary.BigEndian, common.LeftPadBytes(val.Bytes(), 20)) - case "uint128": - val := big.NewInt(0) - val.SetString(values[i], 10) - binary.Write(&buffer, binary.BigEndian, common.LeftPadBytes(val.Bytes(), 16)) - case "uint64": - val := uint64(0) - fmt.Sscanf(values[i], "%d", &val) - binary.Write(&buffer, binary.BigEndian, common.LeftPadBytes(common.BigToHash(big.NewInt(int64(val))).Bytes(), 8)) - case "uint32": - val := uint32(0) - fmt.Sscanf(values[i], "%d", &val) - binary.Write(&buffer, binary.BigEndian, common.LeftPadBytes(common.BigToHash(big.NewInt(int64(val))).Bytes(), 4)) - case "uint16": - val := uint16(0) - fmt.Sscanf(values[i], "%d", &val) - binary.Write(&buffer, binary.BigEndian, common.LeftPadBytes(common.BigToHash(big.NewInt(int64(val))).Bytes(), 2)) - case "uint8": - val := uint8(0) - fmt.Sscanf(values[i], "%d", &val) - buffer.WriteByte(val) - case "address": - buffer.Write(common.HexToAddress(values[i]).Bytes()) - case "bool": - if values[i] == "true" { - buffer.WriteByte(0x01) - } else { - buffer.WriteByte(0x00) - } - case "bytes": - buffer.Write([]byte(values[i])) - case "string": - buffer.Write([]byte(values[i])) - default: - return nil, fmt.Errorf("unsupported type: %s", t) - } - } - - return buffer.Bytes(), nil -} diff --git a/cli/utils/abi/encode_test.go b/cli/utils/abi/encode_test.go deleted file mode 100644 index 7cb554f3e..000000000 --- a/cli/utils/abi/encode_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package abi - -import ( - "bytes" - "testing" - - "github.com/ethereum/go-ethereum/common/hexutil" -) - -func TestEncodePacked(t *testing.T) { - tests := []struct { - signature string - values []string - expected hexutil.Bytes - err bool - }{ - { - "(uint256,address,uint8,bool,string)", - []string{"23123", "0xDEd0000E32f8F40414d3ab3a830f735a3553E18e", "4", "true", "hello"}, - hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000005a53ded0000e32f8f40414d3ab3a830f735a3553e18e040168656c6c6f"), - false, - }, - { - "(bytes32)", - []string{"0x123456789012345678901234567890123456789012345678901234567890abcd"}, - hexutil.MustDecode("0x123456789012345678901234567890123456789012345678901234567890abcd"), - false, - }, - { - "(bytes32,uint256)", - []string{"0x123456789012345678901234567890123456789012345678901234567890abcd", "42"}, - hexutil.MustDecode("0x123456789012345678901234567890123456789012345678901234567890abcd000000000000000000000000000000000000000000000000000000000000002a"), // 32 bytes for bytes32, 32 bytes for uint256 - false, - }, - { - "(bytes)", - []string{"hello"}, - []byte("hello"), - false, - }, - { - "(string)", - []string{"world"}, - []byte("world"), - false, - }, - { - "(uint256,bool)", - []string{"0", "false"}, - hexutil.MustDecode("0x000000000000000000000000000000000000000000000000000000000000000000"), // 32 bytes of zero, plus 1 byte of zero - false, - }, - { - "(string,uint8)", - []string{"test", "255"}, - hexutil.MustDecode("0x74657374ff"), // "test" as ASCII, followed by 255 as a single byte - false, - }, - { - "(uint256,address)", - []string{"1"}, - nil, - true, // Mismatch in number of types and values - }, - { - "(unsupportedType)", - []string{"value"}, - nil, - true, // Unsupported type - }, - { - "()", - []string{}, // Empty values slice - hexutil.MustDecode("0x"), // Empty byte slice - false, - }, - { - "(uint256)", - []string{"115792089237316195423570985008687907853269984665640564039457584007913129639935"}, // 2^256 - 1 - hexutil.MustDecode("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), // 32 bytes of 0xff - false, - }, - } - - for _, test := range tests { - result, err := EncodePacked(test.signature, test.values) - if (err != nil) != test.err { - t.Errorf("Unexpected error for signature %s: %v", test.signature, err) - continue - } - if !bytes.Equal(result, test.expected) { - t.Errorf("Unexpected result for signature %s:\n- got (hex): %x\n- got (bytes): %v\n- want (hex): %s\n- want (bytes): %v", test.signature, result, result, hexutil.Encode(test.expected), test.expected) - } - } -} diff --git a/gnarkx/succinct/circuit_test.go b/gnarkx/succinct/circuit_test.go index d560cc14e..1b0afc9e2 100644 --- a/gnarkx/succinct/circuit_test.go +++ b/gnarkx/succinct/circuit_test.go @@ -27,6 +27,10 @@ func NewTestCircuit() *TestCircuit { } } +func (c *TestCircuit) Assign(in []byte) error { + return nil +} + func (c *TestCircuit) GetInputBytes() *[]vars.Byte { return &c.InputBytes } @@ -81,10 +85,19 @@ func TestSimpleCircuit(t *testing.T) { // sha256(input) expectedInputHash, err := hex.DecodeString("ae964f1e8905240278a7429d6573ba715baf3f4134693c94533ba8a7e57b636e") + if err != nil { + t.Fatal(err) + } // uint64(489) expectedOutput, err := hex.DecodeString("00000000000001e9") + if err != nil { + t.Fatal(err) + } // sha256(uint64(489)) expectedOutputHash, err := hex.DecodeString("080f024e0afaa2f4ed40a8bb08976d6c1bf771342a7ddec9de94a97c0598846a") + if err != nil { + t.Fatal(err) + } // Truncate hashes to rightmost 253 bits as we would in Solidity truncatedInputHash := byteutils.TruncateBytes32([32]byte(expectedInputHash), 253) diff --git a/plonky2x/.gitignore b/plonky2x/.gitignore deleted file mode 100644 index 1669552f3..000000000 --- a/plonky2x/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Cargo -/target - -# Build -/build diff --git a/plonky2x/README.md b/plonky2x/README.md deleted file mode 100644 index cd8027022..000000000 --- a/plonky2x/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# plonky2-gadgets - -General gadgets for plonky2. - - -# Num Gadgets - -Plonky2 Gadgets for u32 and bignum arithmetic. - diff --git a/plonky2x/Cargo.toml b/plonky2x/core/Cargo.toml similarity index 97% rename from plonky2x/Cargo.toml rename to plonky2x/core/Cargo.toml index 8366ee0b3..395ac5996 100644 --- a/plonky2x/Cargo.toml +++ b/plonky2x/core/Cargo.toml @@ -15,7 +15,7 @@ ci = [] [dependencies] plonky2 = { git = "https://github.com/mir-protocol/plonky2.git", default-features = false } curta = { git = "https://github.com/succinctlabs/curta.git" } -plonky2x-derive = { path = "../plonky2x-derive" } +plonky2x-derive = { path = "../derive" } num = { version = "0.4", default-features = false } sha2 = "0.10.7" diff --git a/plonky2x/examples/evm.json b/plonky2x/core/examples/evm.json similarity index 100% rename from plonky2x/examples/evm.json rename to plonky2x/core/examples/evm.json diff --git a/plonky2x/examples/evm.rs b/plonky2x/core/examples/evm.rs similarity index 94% rename from plonky2x/examples/evm.rs rename to plonky2x/core/examples/evm.rs index 7b224f3aa..f98ea70d5 100644 --- a/plonky2x/examples/evm.rs +++ b/plonky2x/core/examples/evm.rs @@ -16,7 +16,7 @@ //! Note that this circuit will not work with field-based io. use plonky2x::backend::circuit::{Circuit, PlonkParameters}; -use plonky2x::backend::function::VerifiableFunction; +use plonky2x::backend::function::Plonky2xFunction; use plonky2x::frontend::vars::ByteVariable; use plonky2x::prelude::CircuitBuilder; @@ -33,7 +33,7 @@ impl Circuit for SimpleAdditionCircuit { } fn main() { - VerifiableFunction::::entrypoint(); + SimpleAdditionCircuit::entrypoint(); } #[cfg(test)] diff --git a/plonky2x/examples/field.json b/plonky2x/core/examples/field.json similarity index 100% rename from plonky2x/examples/field.json rename to plonky2x/core/examples/field.json diff --git a/plonky2x/examples/field.rs b/plonky2x/core/examples/field.rs similarity index 94% rename from plonky2x/examples/field.rs rename to plonky2x/core/examples/field.rs index 343e085e9..6b0770a23 100644 --- a/plonky2x/examples/field.rs +++ b/plonky2x/core/examples/field.rs @@ -16,7 +16,7 @@ //! Note that this circuit will not work with evm-based io. use plonky2x::backend::circuit::{Circuit, PlonkParameters}; -use plonky2x::backend::function::VerifiableFunction; +use plonky2x::backend::function::Plonky2xFunction; use plonky2x::prelude::{CircuitBuilder, Variable}; #[derive(Debug, Clone)] @@ -32,7 +32,7 @@ impl Circuit for SimpleCircuit { } fn main() { - VerifiableFunction::::entrypoint(); + SimpleCircuit::entrypoint(); } #[cfg(test)] diff --git a/plonky2x/examples/mapreduce_balances.rs b/plonky2x/core/examples/mapreduce_balances.rs similarity index 97% rename from plonky2x/examples/mapreduce_balances.rs rename to plonky2x/core/examples/mapreduce_balances.rs index af817f591..75f76687c 100644 --- a/plonky2x/examples/mapreduce_balances.rs +++ b/plonky2x/core/examples/mapreduce_balances.rs @@ -1,7 +1,7 @@ use itertools::Itertools; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; use plonky2x::backend::circuit::{Circuit, DefaultSerializer, PlonkParameters}; -use plonky2x::backend::function::VerifiableFunction; +use plonky2x::backend::function::Plonky2xFunction; use plonky2x::frontend::eth::beacon::vars::BeaconBalancesVariable; use plonky2x::frontend::mapreduce::generator::MapReduceGenerator; use plonky2x::frontend::uint::uint64::U64Variable; @@ -101,7 +101,7 @@ impl Circuit for MapReduceBalanceCircuit { } fn main() { - VerifiableFunction::::entrypoint(); + MapReduceBalanceCircuit::entrypoint(); } #[cfg(test)] diff --git a/plonky2x/examples/mapreduce_validators.rs b/plonky2x/core/examples/mapreduce_validators.rs similarity index 98% rename from plonky2x/examples/mapreduce_validators.rs rename to plonky2x/core/examples/mapreduce_validators.rs index 02832d017..12a3b93f4 100644 --- a/plonky2x/examples/mapreduce_validators.rs +++ b/plonky2x/core/examples/mapreduce_validators.rs @@ -3,7 +3,7 @@ use itertools::Itertools; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; use plonky2x::backend::circuit::{Circuit, DefaultSerializer, PlonkParameters}; -use plonky2x::backend::function::VerifiableFunction; +use plonky2x::backend::function::Plonky2xFunction; use plonky2x::frontend::eth::beacon::vars::{BeaconBalancesVariable, BeaconValidatorsVariable}; use plonky2x::frontend::mapreduce::generator::MapReduceGenerator; use plonky2x::frontend::uint::uint64::U64Variable; @@ -144,7 +144,7 @@ impl Circuit for MapReduceValidatorCircuit { } fn main() { - VerifiableFunction::::entrypoint(); + MapReduceValidatorCircuit::entrypoint(); } #[cfg(test)] diff --git a/plonky2x/src/backend/circuit/build.rs b/plonky2x/core/src/backend/circuit/build.rs similarity index 100% rename from plonky2x/src/backend/circuit/build.rs rename to plonky2x/core/src/backend/circuit/build.rs diff --git a/plonky2x/src/backend/circuit/config.rs b/plonky2x/core/src/backend/circuit/config.rs similarity index 90% rename from plonky2x/src/backend/circuit/config.rs rename to plonky2x/core/src/backend/circuit/config.rs index c0717a124..ea83a6fa6 100644 --- a/plonky2x/src/backend/circuit/config.rs +++ b/plonky2x/core/src/backend/circuit/config.rs @@ -43,10 +43,11 @@ impl PlonkParameters<2> for DefaultParameters { type CurtaConfig = CurtaPoseidonGoldilocksConfig; } +/// Wrapper parameters for the circuit. Uses the `PoseidonBN128GoldilocksConfig` in Plonky2. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct Groth16VerifierParameters; +pub struct Groth16WrapperParameters; -impl PlonkParameters<2> for Groth16VerifierParameters { +impl PlonkParameters<2> for Groth16WrapperParameters { type Field = GoldilocksField; type CubicParams = GoldilocksCubicParameters; diff --git a/plonky2x/src/backend/circuit/input.rs b/plonky2x/core/src/backend/circuit/input.rs similarity index 100% rename from plonky2x/src/backend/circuit/input.rs rename to plonky2x/core/src/backend/circuit/input.rs diff --git a/plonky2x/src/backend/circuit/mock.rs b/plonky2x/core/src/backend/circuit/mock.rs similarity index 100% rename from plonky2x/src/backend/circuit/mock.rs rename to plonky2x/core/src/backend/circuit/mock.rs diff --git a/plonky2x/src/backend/circuit/mod.rs b/plonky2x/core/src/backend/circuit/mod.rs similarity index 96% rename from plonky2x/src/backend/circuit/mod.rs rename to plonky2x/core/src/backend/circuit/mod.rs index 62e645c36..4b6635ab6 100644 --- a/plonky2x/src/backend/circuit/mod.rs +++ b/plonky2x/core/src/backend/circuit/mod.rs @@ -11,7 +11,7 @@ use core::fmt::Debug; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; pub use self::build::CircuitBuild; -pub use self::config::{DefaultParameters, Groth16VerifierParameters, PlonkParameters}; +pub use self::config::{DefaultParameters, Groth16WrapperParameters, PlonkParameters}; pub use self::input::PublicInput; pub use self::mock::MockCircuitBuild; pub use self::output::PublicOutput; diff --git a/plonky2x/src/backend/circuit/output.rs b/plonky2x/core/src/backend/circuit/output.rs similarity index 100% rename from plonky2x/src/backend/circuit/output.rs rename to plonky2x/core/src/backend/circuit/output.rs diff --git a/plonky2x/src/backend/circuit/serialization/gates.rs b/plonky2x/core/src/backend/circuit/serialization/gates.rs similarity index 100% rename from plonky2x/src/backend/circuit/serialization/gates.rs rename to plonky2x/core/src/backend/circuit/serialization/gates.rs diff --git a/plonky2x/src/backend/circuit/serialization/hints.rs b/plonky2x/core/src/backend/circuit/serialization/hints.rs similarity index 100% rename from plonky2x/src/backend/circuit/serialization/hints.rs rename to plonky2x/core/src/backend/circuit/serialization/hints.rs diff --git a/plonky2x/src/backend/circuit/serialization/mod.rs b/plonky2x/core/src/backend/circuit/serialization/mod.rs similarity index 100% rename from plonky2x/src/backend/circuit/serialization/mod.rs rename to plonky2x/core/src/backend/circuit/serialization/mod.rs diff --git a/plonky2x/src/backend/circuit/serialization/registry.rs b/plonky2x/core/src/backend/circuit/serialization/registry.rs similarity index 100% rename from plonky2x/src/backend/circuit/serialization/registry.rs rename to plonky2x/core/src/backend/circuit/serialization/registry.rs diff --git a/plonky2x/src/backend/circuit/witness.rs b/plonky2x/core/src/backend/circuit/witness.rs similarity index 100% rename from plonky2x/src/backend/circuit/witness.rs rename to plonky2x/core/src/backend/circuit/witness.rs diff --git a/plonky2x/src/backend/function/cli.rs b/plonky2x/core/src/backend/function/args.rs similarity index 65% rename from plonky2x/src/backend/function/cli.rs rename to plonky2x/core/src/backend/function/args.rs index c7103f0e0..7f6c9dafc 100644 --- a/plonky2x/src/backend/function/cli.rs +++ b/plonky2x/core/src/backend/function/args.rs @@ -2,44 +2,29 @@ use clap::{Parser, Subcommand}; #[derive(Parser, Debug, Clone)] #[command(about = "Compile a circuit.")] -pub struct BuildArgs { +pub struct CompileArgs { #[arg(long, default_value = "./build")] pub build_dir: String, } -#[derive(Parser, Debug, Clone)] -#[command(about = "Generate a proof for a circuit.")] -pub struct ProveArgs { - #[arg(long, default_value = "./build")] - pub build_dir: String, - - #[clap(long)] - pub input_json: String, - - #[arg(long, default_value = "")] - pub wrapper_path: String, -} - #[derive(Parser, Debug, Clone)] #[command( about = "Generate a proof for a circuit and wrap it into a groth16 proof using the gnark verifier." )] -pub struct ProveWrappedArgs { +pub struct ProveArgs { + pub input_json: String, + #[arg(long, default_value = "./build")] pub build_dir: String, - #[clap(long)] - pub input_json: String, - #[arg(long)] pub wrapper_path: String, } #[derive(Subcommand, Debug, Clone)] pub enum Commands { - Build(BuildArgs), + Compile(CompileArgs), Prove(ProveArgs), - ProveWrapped(ProveWrappedArgs), } #[derive(Parser, Debug, Clone)] diff --git a/plonky2x/src/backend/function/mod.rs b/plonky2x/core/src/backend/function/mod.rs similarity index 71% rename from plonky2x/src/backend/function/mod.rs rename to plonky2x/core/src/backend/function/mod.rs index dc68a0f81..3ffb65a50 100644 --- a/plonky2x/src/backend/function/mod.rs +++ b/plonky2x/core/src/backend/function/mod.rs @@ -1,6 +1,6 @@ -mod cli; -mod request; -mod result; +pub mod args; +pub mod request; +pub mod result; use std::fs::File; use std::io::{BufReader, Write}; @@ -10,47 +10,53 @@ use clap::Parser; use log::info; use plonky2::field::types::PrimeField64; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, GenericHashOut}; -pub use request::{ - BytesRequestData, ElementsRequestData, ProofRequest, ProofRequestBase, - RecursiveProofsRequestData, -}; -pub use result::{ - BytesResultData, ElementsResultData, ProofResult, ProofResultBase, RecursiveProofsResultData, -}; +pub use request::*; +pub use result::*; use serde::Serialize; use sha2::Digest; -use self::cli::{BuildArgs, ProveArgs, ProveWrappedArgs}; -use crate::backend::circuit::config::Groth16VerifierParameters; -use crate::backend::circuit::{ - Circuit, CircuitBuild, DefaultParameters, PlonkParameters, PublicOutput, -}; -use crate::backend::function::cli::{Args, Commands}; +use self::args::{CompileArgs, ProveArgs}; +use crate::backend::circuit::*; +use crate::backend::function::args::{Args, Commands}; use crate::backend::wrapper::wrap::WrappedCircuit; use crate::frontend::builder::CircuitIO; use crate::prelude::{CircuitBuilder, GateRegistry, HintRegistry}; const VERIFIER_CONTRACT: &str = include_str!("../../resources/Verifier.sol"); -pub struct VerifiableFunction { - _phantom: std::marker::PhantomData, +/// `Plonky2xFunction`s have all necessary code for a circuit to be deployed end-to-end. +pub trait Plonky2xFunction { + /// Builds the circuit and saves it to disk. + fn compile, const D: usize>(args: CompileArgs) + where + <>::Config as GenericConfig>::Hasher: AlgebraicHasher; + + /// Generates a proof for the circuit and saves it to disk. + fn prove< + InnerParameters: PlonkParameters, + OuterParameters: PlonkParameters, + const D: usize, + >( + args: ProveArgs, + request: ProofRequest, + ) where + >::Hasher: + AlgebraicHasher, + OuterParameters::Config: Serialize; + + /// The entry point for the function when using the CLI. + fn entrypoint(); + + /// Returns the verifier contract for the circuit. + fn verifier(circuit_digest: &str) -> String; } -/// Circuits that implement `VerifiableFunction` have all necessary code for end-to-end deployment. -/// -/// Conforming to this trait enables remote machines can generate proofs for you. In particular, -/// this trait ensures that the circuit can be built, serialized, and deserialized. -/// -/// You may need to override the default implementation for `generators` and `gates` if you are -/// using custom gates or custom witness generators. -/// -/// Look at the `plonky2x/examples` for examples of how to use this trait. -impl VerifiableFunction { - /// Builds the circuit and saves it to disk. - pub fn compile, const D: usize>(args: BuildArgs) +impl Plonky2xFunction for C { + fn compile, const D: usize>(args: CompileArgs) where <>::Config as GenericConfig>::Hasher: AlgebraicHasher, { + // Build the circuit. info!("Building circuit..."); let mut builder = CircuitBuilder::::new(); C::define::(&mut builder); @@ -59,6 +65,8 @@ impl VerifiableFunction { info!("> Circuit: {}", circuit.id()); info!("> Degree: {}", circuit.data.common.degree()); info!("> Number of Gates: {}", circuit.data.common.gates.len()); + + // Serialize the circuit to disk. let path = format!("{}/main.circuit", args.build_dir); let mut generator_registry = HintRegistry::new(); let mut gate_registry = GateRegistry::new(); @@ -67,7 +75,7 @@ impl VerifiableFunction { circuit.save(&path, &gate_registry, &generator_registry); info!("Successfully saved circuit to disk at {}.", path); - // If the circuit has Bytes IO, we generate the wrapped verifier contract + // Serialize the verifier contract to disk. if let CircuitIO::Bytes(_) = circuit.io { info!("Building verifier contract..."); let contract_path = format!("{}/FunctionVerifier.sol", args.build_dir); @@ -81,8 +89,6 @@ impl VerifiableFunction { .iter() .flat_map(|e| e.to_canonical_u64().to_be_bytes()) .collect::>(); - - // See backend::wrapper::wrap::WrappedCircuit::build for how full circuit digest is computed let full_circuit_digest_bytes = circuit .data .verifier_only @@ -96,9 +102,7 @@ impl VerifiableFunction { }) .chain(circuit_digest_bytes.iter().copied()) .collect::>(); - let circuit_digest_hash = sha2::Sha256::digest(full_circuit_digest_bytes); - assert!( circuit_digest_hash.len() <= 32, "circuit digest must be <= 32 bytes" @@ -109,8 +113,7 @@ impl VerifiableFunction { padded[(32 - digest_len)..].copy_from_slice(&circuit_digest_hash); let circuit_digest = format!("0x{}", hex::encode(padded)); - let verifier_contract = Self::get_verifier_contract(&circuit_digest); - + let verifier_contract = Self::verifier(&circuit_digest); contract_file .write_all(verifier_contract.as_bytes()) .unwrap(); @@ -121,55 +124,12 @@ impl VerifiableFunction { } } - pub fn prove, const D: usize>( - args: ProveArgs, - request: ProofRequest, - ) where - <>::Config as GenericConfig>::Hasher: AlgebraicHasher, - { - let mut generator_registry = HintRegistry::new(); - let mut gate_registry = GateRegistry::new(); - C::register_generators::(&mut generator_registry); - C::register_gates::(&mut gate_registry); - - let mut path = match request { - ProofRequest::Bytes(_) => { - format!("{}/main.circuit", args.build_dir) - } - ProofRequest::Elements(ref request) => { - format!("{}/{}.circuit", args.build_dir, request.data.circuit_id) - } - ProofRequest::RecursiveProofs(ref request) => { - format!("{}/{}.circuit", args.build_dir, request.data.circuit_id) - } - _ => todo!(), - }; - if fs::metadata(&path).is_err() { - path = format!("{}/main.circuit", args.build_dir); - } - - info!("Loading circuit from {}...", path); - let circuit = - CircuitBuild::::load(&path, &gate_registry, &generator_registry).unwrap(); - info!("Successfully loaded circuit."); - - let input = request.input(); - let (proof, output) = circuit.prove(&input); - info!("Successfully generated proof."); - - let result = ProofResult::from_proof_output(proof, output); - let json = serde_json::to_string_pretty(&result).unwrap(); - let mut file = File::create("output.json").unwrap(); - file.write_all(json.as_bytes()).unwrap(); - info!("Successfully saved proof to disk at output.json."); - } - - fn prove_wrapped< + fn prove< InnerParameters: PlonkParameters, OuterParameters: PlonkParameters, const D: usize, >( - args: ProveWrappedArgs, + args: ProveArgs, request: ProofRequest, ) where >::Hasher: @@ -258,7 +218,7 @@ impl VerifiableFunction { } /// The entry point for the function when using the CLI. - pub fn entrypoint() { + fn entrypoint() { type L = DefaultParameters; const D: usize = 2; @@ -267,21 +227,17 @@ impl VerifiableFunction { let args = Args::parse(); match args.command { - Commands::Build(args) => { + Commands::Compile(args) => { Self::compile::(args); } Commands::Prove(args) => { let request = ProofRequest::::load(&args.input_json); - Self::prove(args, request); - } - Commands::ProveWrapped(args) => { - let request = ProofRequest::::load(&args.input_json); - Self::prove_wrapped::(args, request); + Self::prove::(args, request); } } } - fn get_verifier_contract(circuit_digest: &str) -> String { + fn verifier(circuit_digest: &str) -> String { let generated_contract = VERIFIER_CONTRACT .replace("pragma solidity ^0.8.0;", "pragma solidity ^0.8.16;") .replace("uint256[3] calldata input", "uint256[3] memory input"); diff --git a/plonky2x/src/backend/function/request.rs b/plonky2x/core/src/backend/function/request.rs similarity index 100% rename from plonky2x/src/backend/function/request.rs rename to plonky2x/core/src/backend/function/request.rs diff --git a/plonky2x/src/backend/function/result.rs b/plonky2x/core/src/backend/function/result.rs similarity index 100% rename from plonky2x/src/backend/function/result.rs rename to plonky2x/core/src/backend/function/result.rs diff --git a/plonky2x/src/backend/mod.rs b/plonky2x/core/src/backend/mod.rs similarity index 100% rename from plonky2x/src/backend/mod.rs rename to plonky2x/core/src/backend/mod.rs diff --git a/plonky2x/src/backend/prover/env.rs b/plonky2x/core/src/backend/prover/env.rs similarity index 100% rename from plonky2x/src/backend/prover/env.rs rename to plonky2x/core/src/backend/prover/env.rs diff --git a/plonky2x/src/backend/prover/local.rs b/plonky2x/core/src/backend/prover/local.rs similarity index 100% rename from plonky2x/src/backend/prover/local.rs rename to plonky2x/core/src/backend/prover/local.rs diff --git a/plonky2x/src/backend/prover/mod.rs b/plonky2x/core/src/backend/prover/mod.rs similarity index 100% rename from plonky2x/src/backend/prover/mod.rs rename to plonky2x/core/src/backend/prover/mod.rs diff --git a/plonky2x/src/backend/prover/remote.rs b/plonky2x/core/src/backend/prover/remote.rs similarity index 100% rename from plonky2x/src/backend/prover/remote.rs rename to plonky2x/core/src/backend/prover/remote.rs diff --git a/plonky2x/src/backend/prover/service.rs b/plonky2x/core/src/backend/prover/service.rs similarity index 100% rename from plonky2x/src/backend/prover/service.rs rename to plonky2x/core/src/backend/prover/service.rs diff --git a/plonky2x/src/backend/wrapper/mod.rs b/plonky2x/core/src/backend/wrapper/mod.rs similarity index 100% rename from plonky2x/src/backend/wrapper/mod.rs rename to plonky2x/core/src/backend/wrapper/mod.rs diff --git a/plonky2x/src/backend/wrapper/plonky2_config.rs b/plonky2x/core/src/backend/wrapper/plonky2_config.rs similarity index 100% rename from plonky2x/src/backend/wrapper/plonky2_config.rs rename to plonky2x/core/src/backend/wrapper/plonky2_config.rs diff --git a/plonky2x/src/backend/wrapper/poseidon_bn128.rs b/plonky2x/core/src/backend/wrapper/poseidon_bn128.rs similarity index 100% rename from plonky2x/src/backend/wrapper/poseidon_bn128.rs rename to plonky2x/core/src/backend/wrapper/poseidon_bn128.rs diff --git a/plonky2x/src/backend/wrapper/poseidon_bn128_constants.rs b/plonky2x/core/src/backend/wrapper/poseidon_bn128_constants.rs similarity index 100% rename from plonky2x/src/backend/wrapper/poseidon_bn128_constants.rs rename to plonky2x/core/src/backend/wrapper/poseidon_bn128_constants.rs diff --git a/plonky2x/src/backend/wrapper/utils.rs b/plonky2x/core/src/backend/wrapper/utils.rs similarity index 100% rename from plonky2x/src/backend/wrapper/utils.rs rename to plonky2x/core/src/backend/wrapper/utils.rs diff --git a/plonky2x/src/backend/wrapper/wrap.rs b/plonky2x/core/src/backend/wrapper/wrap.rs similarity index 99% rename from plonky2x/src/backend/wrapper/wrap.rs rename to plonky2x/core/src/backend/wrapper/wrap.rs index ef8756f42..d870346c0 100644 --- a/plonky2x/src/backend/wrapper/wrap.rs +++ b/plonky2x/core/src/backend/wrapper/wrap.rs @@ -283,7 +283,7 @@ mod tests { use plonky2::field::types::Field; use super::*; - use crate::backend::circuit::{DefaultParameters, Groth16VerifierParameters}; + use crate::backend::circuit::{DefaultParameters, Groth16WrapperParameters}; use crate::frontend::builder::CircuitBuilder; use crate::frontend::hash::sha::sha256::sha256; use crate::prelude::*; @@ -310,7 +310,7 @@ mod tests { type F = GoldilocksField; const D: usize = 2; type InnerParameters = DefaultParameters; - type OuterParameters = Groth16VerifierParameters; + type OuterParameters = Groth16WrapperParameters; utils::setup_logger(); diff --git a/plonky2x/src/frontend/builder/boolean.rs b/plonky2x/core/src/frontend/builder/boolean.rs similarity index 100% rename from plonky2x/src/frontend/builder/boolean.rs rename to plonky2x/core/src/frontend/builder/boolean.rs diff --git a/plonky2x/src/frontend/builder/io.rs b/plonky2x/core/src/frontend/builder/io.rs similarity index 100% rename from plonky2x/src/frontend/builder/io.rs rename to plonky2x/core/src/frontend/builder/io.rs diff --git a/plonky2x/src/frontend/builder/mod.rs b/plonky2x/core/src/frontend/builder/mod.rs similarity index 100% rename from plonky2x/src/frontend/builder/mod.rs rename to plonky2x/core/src/frontend/builder/mod.rs diff --git a/plonky2x/src/frontend/builder/proof.rs b/plonky2x/core/src/frontend/builder/proof.rs similarity index 100% rename from plonky2x/src/frontend/builder/proof.rs rename to plonky2x/core/src/frontend/builder/proof.rs diff --git a/plonky2x/src/frontend/builder/watch.rs b/plonky2x/core/src/frontend/builder/watch.rs similarity index 100% rename from plonky2x/src/frontend/builder/watch.rs rename to plonky2x/core/src/frontend/builder/watch.rs diff --git a/plonky2x/src/frontend/curta/builder.rs b/plonky2x/core/src/frontend/curta/builder.rs similarity index 100% rename from plonky2x/src/frontend/curta/builder.rs rename to plonky2x/core/src/frontend/curta/builder.rs diff --git a/plonky2x/src/frontend/curta/ec/aggregate/air.rs b/plonky2x/core/src/frontend/curta/ec/aggregate/air.rs similarity index 100% rename from plonky2x/src/frontend/curta/ec/aggregate/air.rs rename to plonky2x/core/src/frontend/curta/ec/aggregate/air.rs diff --git a/plonky2x/src/frontend/curta/ec/aggregate/builder.rs b/plonky2x/core/src/frontend/curta/ec/aggregate/builder.rs similarity index 100% rename from plonky2x/src/frontend/curta/ec/aggregate/builder.rs rename to plonky2x/core/src/frontend/curta/ec/aggregate/builder.rs diff --git a/plonky2x/src/frontend/curta/ec/aggregate/hint.rs b/plonky2x/core/src/frontend/curta/ec/aggregate/hint.rs similarity index 100% rename from plonky2x/src/frontend/curta/ec/aggregate/hint.rs rename to plonky2x/core/src/frontend/curta/ec/aggregate/hint.rs diff --git a/plonky2x/src/frontend/curta/ec/aggregate/mod.rs b/plonky2x/core/src/frontend/curta/ec/aggregate/mod.rs similarity index 100% rename from plonky2x/src/frontend/curta/ec/aggregate/mod.rs rename to plonky2x/core/src/frontend/curta/ec/aggregate/mod.rs diff --git a/plonky2x/src/frontend/curta/ec/mod.rs b/plonky2x/core/src/frontend/curta/ec/mod.rs similarity index 100% rename from plonky2x/src/frontend/curta/ec/mod.rs rename to plonky2x/core/src/frontend/curta/ec/mod.rs diff --git a/plonky2x/src/frontend/curta/ec/point.rs b/plonky2x/core/src/frontend/curta/ec/point.rs similarity index 100% rename from plonky2x/src/frontend/curta/ec/point.rs rename to plonky2x/core/src/frontend/curta/ec/point.rs diff --git a/plonky2x/src/frontend/curta/field/mod.rs b/plonky2x/core/src/frontend/curta/field/mod.rs similarity index 100% rename from plonky2x/src/frontend/curta/field/mod.rs rename to plonky2x/core/src/frontend/curta/field/mod.rs diff --git a/plonky2x/src/frontend/curta/field/variable.rs b/plonky2x/core/src/frontend/curta/field/variable.rs similarity index 100% rename from plonky2x/src/frontend/curta/field/variable.rs rename to plonky2x/core/src/frontend/curta/field/variable.rs diff --git a/plonky2x/src/frontend/curta/hash/mod.rs b/plonky2x/core/src/frontend/curta/hash/mod.rs similarity index 100% rename from plonky2x/src/frontend/curta/hash/mod.rs rename to plonky2x/core/src/frontend/curta/hash/mod.rs diff --git a/plonky2x/src/frontend/curta/hash/sha/mod.rs b/plonky2x/core/src/frontend/curta/hash/sha/mod.rs similarity index 100% rename from plonky2x/src/frontend/curta/hash/sha/mod.rs rename to plonky2x/core/src/frontend/curta/hash/sha/mod.rs diff --git a/plonky2x/src/frontend/curta/hash/sha/sha256/builder.rs b/plonky2x/core/src/frontend/curta/hash/sha/sha256/builder.rs similarity index 100% rename from plonky2x/src/frontend/curta/hash/sha/sha256/builder.rs rename to plonky2x/core/src/frontend/curta/hash/sha/sha256/builder.rs diff --git a/plonky2x/src/frontend/curta/hash/sha/sha256/hint.rs b/plonky2x/core/src/frontend/curta/hash/sha/sha256/hint.rs similarity index 100% rename from plonky2x/src/frontend/curta/hash/sha/sha256/hint.rs rename to plonky2x/core/src/frontend/curta/hash/sha/sha256/hint.rs diff --git a/plonky2x/src/frontend/curta/hash/sha/sha256/mod.rs b/plonky2x/core/src/frontend/curta/hash/sha/sha256/mod.rs similarity index 100% rename from plonky2x/src/frontend/curta/hash/sha/sha256/mod.rs rename to plonky2x/core/src/frontend/curta/hash/sha/sha256/mod.rs diff --git a/plonky2x/src/frontend/curta/mod.rs b/plonky2x/core/src/frontend/curta/mod.rs similarity index 100% rename from plonky2x/src/frontend/curta/mod.rs rename to plonky2x/core/src/frontend/curta/mod.rs diff --git a/plonky2x/src/frontend/curta/proof.rs b/plonky2x/core/src/frontend/curta/proof.rs similarity index 100% rename from plonky2x/src/frontend/curta/proof.rs rename to plonky2x/core/src/frontend/curta/proof.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/curve/curve_adds.rs b/plonky2x/core/src/frontend/ecc/ed25519/curve/curve_adds.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/curve/curve_adds.rs rename to plonky2x/core/src/frontend/ecc/ed25519/curve/curve_adds.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/curve/curve_multiplication.rs b/plonky2x/core/src/frontend/ecc/ed25519/curve/curve_multiplication.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/curve/curve_multiplication.rs rename to plonky2x/core/src/frontend/ecc/ed25519/curve/curve_multiplication.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/curve/curve_types.rs b/plonky2x/core/src/frontend/ecc/ed25519/curve/curve_types.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/curve/curve_types.rs rename to plonky2x/core/src/frontend/ecc/ed25519/curve/curve_types.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/curve/ed25519.rs b/plonky2x/core/src/frontend/ecc/ed25519/curve/ed25519.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/curve/ed25519.rs rename to plonky2x/core/src/frontend/ecc/ed25519/curve/ed25519.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/curve/eddsa.rs b/plonky2x/core/src/frontend/ecc/ed25519/curve/eddsa.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/curve/eddsa.rs rename to plonky2x/core/src/frontend/ecc/ed25519/curve/eddsa.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/curve/mod.rs b/plonky2x/core/src/frontend/ecc/ed25519/curve/mod.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/curve/mod.rs rename to plonky2x/core/src/frontend/ecc/ed25519/curve/mod.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/field/ed25519_base.rs b/plonky2x/core/src/frontend/ecc/ed25519/field/ed25519_base.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/field/ed25519_base.rs rename to plonky2x/core/src/frontend/ecc/ed25519/field/ed25519_base.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/field/ed25519_scalar.rs b/plonky2x/core/src/frontend/ecc/ed25519/field/ed25519_scalar.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/field/ed25519_scalar.rs rename to plonky2x/core/src/frontend/ecc/ed25519/field/ed25519_scalar.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/field/field_testing.rs b/plonky2x/core/src/frontend/ecc/ed25519/field/field_testing.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/field/field_testing.rs rename to plonky2x/core/src/frontend/ecc/ed25519/field/field_testing.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/field/mod.rs b/plonky2x/core/src/frontend/ecc/ed25519/field/mod.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/field/mod.rs rename to plonky2x/core/src/frontend/ecc/ed25519/field/mod.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/gadgets/curve.rs b/plonky2x/core/src/frontend/ecc/ed25519/gadgets/curve.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/gadgets/curve.rs rename to plonky2x/core/src/frontend/ecc/ed25519/gadgets/curve.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/gadgets/eddsa.rs b/plonky2x/core/src/frontend/ecc/ed25519/gadgets/eddsa.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/gadgets/eddsa.rs rename to plonky2x/core/src/frontend/ecc/ed25519/gadgets/eddsa.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/gadgets/mod.rs b/plonky2x/core/src/frontend/ecc/ed25519/gadgets/mod.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/gadgets/mod.rs rename to plonky2x/core/src/frontend/ecc/ed25519/gadgets/mod.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/gadgets/verify.rs b/plonky2x/core/src/frontend/ecc/ed25519/gadgets/verify.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/gadgets/verify.rs rename to plonky2x/core/src/frontend/ecc/ed25519/gadgets/verify.rs diff --git a/plonky2x/src/frontend/ecc/ed25519/mod.rs b/plonky2x/core/src/frontend/ecc/ed25519/mod.rs similarity index 100% rename from plonky2x/src/frontend/ecc/ed25519/mod.rs rename to plonky2x/core/src/frontend/ecc/ed25519/mod.rs diff --git a/plonky2x/src/frontend/ecc/mod.rs b/plonky2x/core/src/frontend/ecc/mod.rs similarity index 100% rename from plonky2x/src/frontend/ecc/mod.rs rename to plonky2x/core/src/frontend/ecc/mod.rs diff --git a/plonky2x/src/frontend/eth/beacon/builder.rs b/plonky2x/core/src/frontend/eth/beacon/builder.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/builder.rs rename to plonky2x/core/src/frontend/eth/beacon/builder.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/all_withdrawals.rs b/plonky2x/core/src/frontend/eth/beacon/generators/all_withdrawals.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/all_withdrawals.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/all_withdrawals.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/balance.rs b/plonky2x/core/src/frontend/eth/beacon/generators/balance.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/balance.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/balance.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/balance_witness.rs b/plonky2x/core/src/frontend/eth/beacon/generators/balance_witness.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/balance_witness.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/balance_witness.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/balances.rs b/plonky2x/core/src/frontend/eth/beacon/generators/balances.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/balances.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/balances.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/eth1_block.rs b/plonky2x/core/src/frontend/eth/beacon/generators/eth1_block.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/eth1_block.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/eth1_block.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/header.rs b/plonky2x/core/src/frontend/eth/beacon/generators/header.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/header.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/header.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/historical.rs b/plonky2x/core/src/frontend/eth/beacon/generators/historical.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/historical.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/historical.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/mod.rs b/plonky2x/core/src/frontend/eth/beacon/generators/mod.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/mod.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/mod.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/partial_balances.rs b/plonky2x/core/src/frontend/eth/beacon/generators/partial_balances.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/partial_balances.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/partial_balances.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/partial_validators.rs b/plonky2x/core/src/frontend/eth/beacon/generators/partial_validators.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/partial_validators.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/partial_validators.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/validator.rs b/plonky2x/core/src/frontend/eth/beacon/generators/validator.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/validator.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/validator.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/validator_witness.rs b/plonky2x/core/src/frontend/eth/beacon/generators/validator_witness.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/validator_witness.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/validator_witness.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/validators.rs b/plonky2x/core/src/frontend/eth/beacon/generators/validators.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/validators.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/validators.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/withdrawal.rs b/plonky2x/core/src/frontend/eth/beacon/generators/withdrawal.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/withdrawal.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/withdrawal.rs diff --git a/plonky2x/src/frontend/eth/beacon/generators/withdrawals.rs b/plonky2x/core/src/frontend/eth/beacon/generators/withdrawals.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/generators/withdrawals.rs rename to plonky2x/core/src/frontend/eth/beacon/generators/withdrawals.rs diff --git a/plonky2x/src/frontend/eth/beacon/mod.rs b/plonky2x/core/src/frontend/eth/beacon/mod.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/mod.rs rename to plonky2x/core/src/frontend/eth/beacon/mod.rs diff --git a/plonky2x/src/frontend/eth/beacon/vars/balances.rs b/plonky2x/core/src/frontend/eth/beacon/vars/balances.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/vars/balances.rs rename to plonky2x/core/src/frontend/eth/beacon/vars/balances.rs diff --git a/plonky2x/src/frontend/eth/beacon/vars/compressed_validator.rs b/plonky2x/core/src/frontend/eth/beacon/vars/compressed_validator.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/vars/compressed_validator.rs rename to plonky2x/core/src/frontend/eth/beacon/vars/compressed_validator.rs diff --git a/plonky2x/src/frontend/eth/beacon/vars/header.rs b/plonky2x/core/src/frontend/eth/beacon/vars/header.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/vars/header.rs rename to plonky2x/core/src/frontend/eth/beacon/vars/header.rs diff --git a/plonky2x/src/frontend/eth/beacon/vars/mod.rs b/plonky2x/core/src/frontend/eth/beacon/vars/mod.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/vars/mod.rs rename to plonky2x/core/src/frontend/eth/beacon/vars/mod.rs diff --git a/plonky2x/src/frontend/eth/beacon/vars/validator.rs b/plonky2x/core/src/frontend/eth/beacon/vars/validator.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/vars/validator.rs rename to plonky2x/core/src/frontend/eth/beacon/vars/validator.rs diff --git a/plonky2x/src/frontend/eth/beacon/vars/validators.rs b/plonky2x/core/src/frontend/eth/beacon/vars/validators.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/vars/validators.rs rename to plonky2x/core/src/frontend/eth/beacon/vars/validators.rs diff --git a/plonky2x/src/frontend/eth/beacon/vars/withdrawal.rs b/plonky2x/core/src/frontend/eth/beacon/vars/withdrawal.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/vars/withdrawal.rs rename to plonky2x/core/src/frontend/eth/beacon/vars/withdrawal.rs diff --git a/plonky2x/src/frontend/eth/beacon/vars/withdrawals.rs b/plonky2x/core/src/frontend/eth/beacon/vars/withdrawals.rs similarity index 100% rename from plonky2x/src/frontend/eth/beacon/vars/withdrawals.rs rename to plonky2x/core/src/frontend/eth/beacon/vars/withdrawals.rs diff --git a/plonky2x/src/frontend/eth/mod.rs b/plonky2x/core/src/frontend/eth/mod.rs similarity index 100% rename from plonky2x/src/frontend/eth/mod.rs rename to plonky2x/core/src/frontend/eth/mod.rs diff --git a/plonky2x/src/frontend/eth/mpt/builder.rs b/plonky2x/core/src/frontend/eth/mpt/builder.rs similarity index 100% rename from plonky2x/src/frontend/eth/mpt/builder.rs rename to plonky2x/core/src/frontend/eth/mpt/builder.rs diff --git a/plonky2x/src/frontend/eth/mpt/fixtures/example.json b/plonky2x/core/src/frontend/eth/mpt/fixtures/example.json similarity index 100% rename from plonky2x/src/frontend/eth/mpt/fixtures/example.json rename to plonky2x/core/src/frontend/eth/mpt/fixtures/example.json diff --git a/plonky2x/src/frontend/eth/mpt/generators.rs b/plonky2x/core/src/frontend/eth/mpt/generators.rs similarity index 100% rename from plonky2x/src/frontend/eth/mpt/generators.rs rename to plonky2x/core/src/frontend/eth/mpt/generators.rs diff --git a/plonky2x/src/frontend/eth/mpt/mod.rs b/plonky2x/core/src/frontend/eth/mpt/mod.rs similarity index 100% rename from plonky2x/src/frontend/eth/mpt/mod.rs rename to plonky2x/core/src/frontend/eth/mpt/mod.rs diff --git a/plonky2x/src/frontend/eth/mpt/reference.rs b/plonky2x/core/src/frontend/eth/mpt/reference.rs similarity index 100% rename from plonky2x/src/frontend/eth/mpt/reference.rs rename to plonky2x/core/src/frontend/eth/mpt/reference.rs diff --git a/plonky2x/src/frontend/eth/mpt/rlc.rs b/plonky2x/core/src/frontend/eth/mpt/rlc.rs similarity index 100% rename from plonky2x/src/frontend/eth/mpt/rlc.rs rename to plonky2x/core/src/frontend/eth/mpt/rlc.rs diff --git a/plonky2x/src/frontend/eth/mpt/utils.rs b/plonky2x/core/src/frontend/eth/mpt/utils.rs similarity index 100% rename from plonky2x/src/frontend/eth/mpt/utils.rs rename to plonky2x/core/src/frontend/eth/mpt/utils.rs diff --git a/plonky2x/src/frontend/eth/rlp/builder.rs b/plonky2x/core/src/frontend/eth/rlp/builder.rs similarity index 100% rename from plonky2x/src/frontend/eth/rlp/builder.rs rename to plonky2x/core/src/frontend/eth/rlp/builder.rs diff --git a/plonky2x/src/frontend/eth/rlp/mod.rs b/plonky2x/core/src/frontend/eth/rlp/mod.rs similarity index 100% rename from plonky2x/src/frontend/eth/rlp/mod.rs rename to plonky2x/core/src/frontend/eth/rlp/mod.rs diff --git a/plonky2x/src/frontend/eth/storage/builder.rs b/plonky2x/core/src/frontend/eth/storage/builder.rs similarity index 100% rename from plonky2x/src/frontend/eth/storage/builder.rs rename to plonky2x/core/src/frontend/eth/storage/builder.rs diff --git a/plonky2x/src/frontend/eth/storage/generators/block.rs b/plonky2x/core/src/frontend/eth/storage/generators/block.rs similarity index 100% rename from plonky2x/src/frontend/eth/storage/generators/block.rs rename to plonky2x/core/src/frontend/eth/storage/generators/block.rs diff --git a/plonky2x/src/frontend/eth/storage/generators/mod.rs b/plonky2x/core/src/frontend/eth/storage/generators/mod.rs similarity index 100% rename from plonky2x/src/frontend/eth/storage/generators/mod.rs rename to plonky2x/core/src/frontend/eth/storage/generators/mod.rs diff --git a/plonky2x/src/frontend/eth/storage/generators/storage.rs b/plonky2x/core/src/frontend/eth/storage/generators/storage.rs similarity index 100% rename from plonky2x/src/frontend/eth/storage/generators/storage.rs rename to plonky2x/core/src/frontend/eth/storage/generators/storage.rs diff --git a/plonky2x/src/frontend/eth/storage/mod.rs b/plonky2x/core/src/frontend/eth/storage/mod.rs similarity index 100% rename from plonky2x/src/frontend/eth/storage/mod.rs rename to plonky2x/core/src/frontend/eth/storage/mod.rs diff --git a/plonky2x/src/frontend/eth/storage/utils.rs b/plonky2x/core/src/frontend/eth/storage/utils.rs similarity index 100% rename from plonky2x/src/frontend/eth/storage/utils.rs rename to plonky2x/core/src/frontend/eth/storage/utils.rs diff --git a/plonky2x/src/frontend/eth/storage/vars/block.rs b/plonky2x/core/src/frontend/eth/storage/vars/block.rs similarity index 100% rename from plonky2x/src/frontend/eth/storage/vars/block.rs rename to plonky2x/core/src/frontend/eth/storage/vars/block.rs diff --git a/plonky2x/src/frontend/eth/storage/vars/mod.rs b/plonky2x/core/src/frontend/eth/storage/vars/mod.rs similarity index 100% rename from plonky2x/src/frontend/eth/storage/vars/mod.rs rename to plonky2x/core/src/frontend/eth/storage/vars/mod.rs diff --git a/plonky2x/src/frontend/eth/storage/vars/storage.rs b/plonky2x/core/src/frontend/eth/storage/vars/storage.rs similarity index 100% rename from plonky2x/src/frontend/eth/storage/vars/storage.rs rename to plonky2x/core/src/frontend/eth/storage/vars/storage.rs diff --git a/plonky2x/src/frontend/eth/utils.rs b/plonky2x/core/src/frontend/eth/utils.rs similarity index 100% rename from plonky2x/src/frontend/eth/utils.rs rename to plonky2x/core/src/frontend/eth/utils.rs diff --git a/plonky2x/src/frontend/eth/vars.rs b/plonky2x/core/src/frontend/eth/vars.rs similarity index 100% rename from plonky2x/src/frontend/eth/vars.rs rename to plonky2x/core/src/frontend/eth/vars.rs diff --git a/plonky2x/src/frontend/hash/bit_operations/mod.rs b/plonky2x/core/src/frontend/hash/bit_operations/mod.rs similarity index 100% rename from plonky2x/src/frontend/hash/bit_operations/mod.rs rename to plonky2x/core/src/frontend/hash/bit_operations/mod.rs diff --git a/plonky2x/src/frontend/hash/bit_operations/u8.rs b/plonky2x/core/src/frontend/hash/bit_operations/u8.rs similarity index 100% rename from plonky2x/src/frontend/hash/bit_operations/u8.rs rename to plonky2x/core/src/frontend/hash/bit_operations/u8.rs diff --git a/plonky2x/src/frontend/hash/bit_operations/util.rs b/plonky2x/core/src/frontend/hash/bit_operations/util.rs similarity index 100% rename from plonky2x/src/frontend/hash/bit_operations/util.rs rename to plonky2x/core/src/frontend/hash/bit_operations/util.rs diff --git a/plonky2x/src/frontend/hash/blake2/blake2b.rs b/plonky2x/core/src/frontend/hash/blake2/blake2b.rs similarity index 100% rename from plonky2x/src/frontend/hash/blake2/blake2b.rs rename to plonky2x/core/src/frontend/hash/blake2/blake2b.rs diff --git a/plonky2x/src/frontend/hash/blake2/blake2b_curta.rs b/plonky2x/core/src/frontend/hash/blake2/blake2b_curta.rs similarity index 100% rename from plonky2x/src/frontend/hash/blake2/blake2b_curta.rs rename to plonky2x/core/src/frontend/hash/blake2/blake2b_curta.rs diff --git a/plonky2x/src/frontend/hash/blake2/mod.rs b/plonky2x/core/src/frontend/hash/blake2/mod.rs similarity index 100% rename from plonky2x/src/frontend/hash/blake2/mod.rs rename to plonky2x/core/src/frontend/hash/blake2/mod.rs diff --git a/plonky2x/src/frontend/hash/keccak/keccak256.rs b/plonky2x/core/src/frontend/hash/keccak/keccak256.rs similarity index 100% rename from plonky2x/src/frontend/hash/keccak/keccak256.rs rename to plonky2x/core/src/frontend/hash/keccak/keccak256.rs diff --git a/plonky2x/src/frontend/hash/keccak/mod.rs b/plonky2x/core/src/frontend/hash/keccak/mod.rs similarity index 100% rename from plonky2x/src/frontend/hash/keccak/mod.rs rename to plonky2x/core/src/frontend/hash/keccak/mod.rs diff --git a/plonky2x/src/frontend/hash/mod.rs b/plonky2x/core/src/frontend/hash/mod.rs similarity index 100% rename from plonky2x/src/frontend/hash/mod.rs rename to plonky2x/core/src/frontend/hash/mod.rs diff --git a/plonky2x/src/frontend/hash/poseidon/mod.rs b/plonky2x/core/src/frontend/hash/poseidon/mod.rs similarity index 100% rename from plonky2x/src/frontend/hash/poseidon/mod.rs rename to plonky2x/core/src/frontend/hash/poseidon/mod.rs diff --git a/plonky2x/src/frontend/hash/poseidon/poseidon256.rs b/plonky2x/core/src/frontend/hash/poseidon/poseidon256.rs similarity index 100% rename from plonky2x/src/frontend/hash/poseidon/poseidon256.rs rename to plonky2x/core/src/frontend/hash/poseidon/poseidon256.rs diff --git a/plonky2x/src/frontend/hash/sha/mod.rs b/plonky2x/core/src/frontend/hash/sha/mod.rs similarity index 100% rename from plonky2x/src/frontend/hash/sha/mod.rs rename to plonky2x/core/src/frontend/hash/sha/mod.rs diff --git a/plonky2x/src/frontend/hash/sha/sha256.rs b/plonky2x/core/src/frontend/hash/sha/sha256.rs similarity index 100% rename from plonky2x/src/frontend/hash/sha/sha256.rs rename to plonky2x/core/src/frontend/hash/sha/sha256.rs diff --git a/plonky2x/src/frontend/hash/sha/sha256_curta.rs b/plonky2x/core/src/frontend/hash/sha/sha256_curta.rs similarity index 100% rename from plonky2x/src/frontend/hash/sha/sha256_curta.rs rename to plonky2x/core/src/frontend/hash/sha/sha256_curta.rs diff --git a/plonky2x/src/frontend/hash/sha/sha512.rs b/plonky2x/core/src/frontend/hash/sha/sha512.rs similarity index 100% rename from plonky2x/src/frontend/hash/sha/sha512.rs rename to plonky2x/core/src/frontend/hash/sha/sha512.rs diff --git a/plonky2x/src/frontend/hint/asynchronous/builder.rs b/plonky2x/core/src/frontend/hint/asynchronous/builder.rs similarity index 100% rename from plonky2x/src/frontend/hint/asynchronous/builder.rs rename to plonky2x/core/src/frontend/hint/asynchronous/builder.rs diff --git a/plonky2x/src/frontend/hint/asynchronous/channel.rs b/plonky2x/core/src/frontend/hint/asynchronous/channel.rs similarity index 100% rename from plonky2x/src/frontend/hint/asynchronous/channel.rs rename to plonky2x/core/src/frontend/hint/asynchronous/channel.rs diff --git a/plonky2x/src/frontend/hint/asynchronous/generator.rs b/plonky2x/core/src/frontend/hint/asynchronous/generator.rs similarity index 100% rename from plonky2x/src/frontend/hint/asynchronous/generator.rs rename to plonky2x/core/src/frontend/hint/asynchronous/generator.rs diff --git a/plonky2x/src/frontend/hint/asynchronous/handler.rs b/plonky2x/core/src/frontend/hint/asynchronous/handler.rs similarity index 100% rename from plonky2x/src/frontend/hint/asynchronous/handler.rs rename to plonky2x/core/src/frontend/hint/asynchronous/handler.rs diff --git a/plonky2x/src/frontend/hint/asynchronous/hint.rs b/plonky2x/core/src/frontend/hint/asynchronous/hint.rs similarity index 100% rename from plonky2x/src/frontend/hint/asynchronous/hint.rs rename to plonky2x/core/src/frontend/hint/asynchronous/hint.rs diff --git a/plonky2x/src/frontend/hint/asynchronous/mod.rs b/plonky2x/core/src/frontend/hint/asynchronous/mod.rs similarity index 100% rename from plonky2x/src/frontend/hint/asynchronous/mod.rs rename to plonky2x/core/src/frontend/hint/asynchronous/mod.rs diff --git a/plonky2x/src/frontend/hint/asynchronous/serializer.rs b/plonky2x/core/src/frontend/hint/asynchronous/serializer.rs similarity index 100% rename from plonky2x/src/frontend/hint/asynchronous/serializer.rs rename to plonky2x/core/src/frontend/hint/asynchronous/serializer.rs diff --git a/plonky2x/src/frontend/hint/mod.rs b/plonky2x/core/src/frontend/hint/mod.rs similarity index 100% rename from plonky2x/src/frontend/hint/mod.rs rename to plonky2x/core/src/frontend/hint/mod.rs diff --git a/plonky2x/src/frontend/hint/simple/generator.rs b/plonky2x/core/src/frontend/hint/simple/generator.rs similarity index 100% rename from plonky2x/src/frontend/hint/simple/generator.rs rename to plonky2x/core/src/frontend/hint/simple/generator.rs diff --git a/plonky2x/src/frontend/hint/simple/hint.rs b/plonky2x/core/src/frontend/hint/simple/hint.rs similarity index 100% rename from plonky2x/src/frontend/hint/simple/hint.rs rename to plonky2x/core/src/frontend/hint/simple/hint.rs diff --git a/plonky2x/src/frontend/hint/simple/mod.rs b/plonky2x/core/src/frontend/hint/simple/mod.rs similarity index 100% rename from plonky2x/src/frontend/hint/simple/mod.rs rename to plonky2x/core/src/frontend/hint/simple/mod.rs diff --git a/plonky2x/src/frontend/hint/simple/serializer.rs b/plonky2x/core/src/frontend/hint/simple/serializer.rs similarity index 100% rename from plonky2x/src/frontend/hint/simple/serializer.rs rename to plonky2x/core/src/frontend/hint/simple/serializer.rs diff --git a/plonky2x/src/frontend/hint/synchronous.rs b/plonky2x/core/src/frontend/hint/synchronous.rs similarity index 100% rename from plonky2x/src/frontend/hint/synchronous.rs rename to plonky2x/core/src/frontend/hint/synchronous.rs diff --git a/plonky2x/src/frontend/mapreduce/generator.rs b/plonky2x/core/src/frontend/mapreduce/generator.rs similarity index 100% rename from plonky2x/src/frontend/mapreduce/generator.rs rename to plonky2x/core/src/frontend/mapreduce/generator.rs diff --git a/plonky2x/src/frontend/mapreduce/mod.rs b/plonky2x/core/src/frontend/mapreduce/mod.rs similarity index 100% rename from plonky2x/src/frontend/mapreduce/mod.rs rename to plonky2x/core/src/frontend/mapreduce/mod.rs diff --git a/plonky2x/src/frontend/merkle/mod.rs b/plonky2x/core/src/frontend/merkle/mod.rs similarity index 100% rename from plonky2x/src/frontend/merkle/mod.rs rename to plonky2x/core/src/frontend/merkle/mod.rs diff --git a/plonky2x/src/frontend/merkle/tendermint.rs b/plonky2x/core/src/frontend/merkle/tendermint.rs similarity index 100% rename from plonky2x/src/frontend/merkle/tendermint.rs rename to plonky2x/core/src/frontend/merkle/tendermint.rs diff --git a/plonky2x/src/frontend/merkle/tree.rs b/plonky2x/core/src/frontend/merkle/tree.rs similarity index 100% rename from plonky2x/src/frontend/merkle/tree.rs rename to plonky2x/core/src/frontend/merkle/tree.rs diff --git a/plonky2x/src/frontend/mod.rs b/plonky2x/core/src/frontend/mod.rs similarity index 100% rename from plonky2x/src/frontend/mod.rs rename to plonky2x/core/src/frontend/mod.rs diff --git a/plonky2x/src/frontend/num/biguint/mod.rs b/plonky2x/core/src/frontend/num/biguint/mod.rs similarity index 100% rename from plonky2x/src/frontend/num/biguint/mod.rs rename to plonky2x/core/src/frontend/num/biguint/mod.rs diff --git a/plonky2x/src/frontend/num/mod.rs b/plonky2x/core/src/frontend/num/mod.rs similarity index 100% rename from plonky2x/src/frontend/num/mod.rs rename to plonky2x/core/src/frontend/num/mod.rs diff --git a/plonky2x/src/frontend/num/nonnative/mod.rs b/plonky2x/core/src/frontend/num/nonnative/mod.rs similarity index 100% rename from plonky2x/src/frontend/num/nonnative/mod.rs rename to plonky2x/core/src/frontend/num/nonnative/mod.rs diff --git a/plonky2x/src/frontend/num/nonnative/nonnative.rs b/plonky2x/core/src/frontend/num/nonnative/nonnative.rs similarity index 100% rename from plonky2x/src/frontend/num/nonnative/nonnative.rs rename to plonky2x/core/src/frontend/num/nonnative/nonnative.rs diff --git a/plonky2x/src/frontend/num/nonnative/split_nonnative.rs b/plonky2x/core/src/frontend/num/nonnative/split_nonnative.rs similarity index 100% rename from plonky2x/src/frontend/num/nonnative/split_nonnative.rs rename to plonky2x/core/src/frontend/num/nonnative/split_nonnative.rs diff --git a/plonky2x/src/frontend/num/u32/gadgets/arithmetic_u32.rs b/plonky2x/core/src/frontend/num/u32/gadgets/arithmetic_u32.rs similarity index 100% rename from plonky2x/src/frontend/num/u32/gadgets/arithmetic_u32.rs rename to plonky2x/core/src/frontend/num/u32/gadgets/arithmetic_u32.rs diff --git a/plonky2x/src/frontend/num/u32/gadgets/mod.rs b/plonky2x/core/src/frontend/num/u32/gadgets/mod.rs similarity index 100% rename from plonky2x/src/frontend/num/u32/gadgets/mod.rs rename to plonky2x/core/src/frontend/num/u32/gadgets/mod.rs diff --git a/plonky2x/src/frontend/num/u32/gadgets/multiple_comparison.rs b/plonky2x/core/src/frontend/num/u32/gadgets/multiple_comparison.rs similarity index 100% rename from plonky2x/src/frontend/num/u32/gadgets/multiple_comparison.rs rename to plonky2x/core/src/frontend/num/u32/gadgets/multiple_comparison.rs diff --git a/plonky2x/src/frontend/num/u32/gadgets/range_check.rs b/plonky2x/core/src/frontend/num/u32/gadgets/range_check.rs similarity index 100% rename from plonky2x/src/frontend/num/u32/gadgets/range_check.rs rename to plonky2x/core/src/frontend/num/u32/gadgets/range_check.rs diff --git a/plonky2x/src/frontend/num/u32/gates/add_many_u32.rs b/plonky2x/core/src/frontend/num/u32/gates/add_many_u32.rs similarity index 100% rename from plonky2x/src/frontend/num/u32/gates/add_many_u32.rs rename to plonky2x/core/src/frontend/num/u32/gates/add_many_u32.rs diff --git a/plonky2x/src/frontend/num/u32/gates/arithmetic_u32.rs b/plonky2x/core/src/frontend/num/u32/gates/arithmetic_u32.rs similarity index 100% rename from plonky2x/src/frontend/num/u32/gates/arithmetic_u32.rs rename to plonky2x/core/src/frontend/num/u32/gates/arithmetic_u32.rs diff --git a/plonky2x/src/frontend/num/u32/gates/comparison.rs b/plonky2x/core/src/frontend/num/u32/gates/comparison.rs similarity index 100% rename from plonky2x/src/frontend/num/u32/gates/comparison.rs rename to plonky2x/core/src/frontend/num/u32/gates/comparison.rs diff --git a/plonky2x/src/frontend/num/u32/gates/mod.rs b/plonky2x/core/src/frontend/num/u32/gates/mod.rs similarity index 100% rename from plonky2x/src/frontend/num/u32/gates/mod.rs rename to plonky2x/core/src/frontend/num/u32/gates/mod.rs diff --git a/plonky2x/src/frontend/num/u32/gates/range_check_u32.rs b/plonky2x/core/src/frontend/num/u32/gates/range_check_u32.rs similarity index 100% rename from plonky2x/src/frontend/num/u32/gates/range_check_u32.rs rename to plonky2x/core/src/frontend/num/u32/gates/range_check_u32.rs diff --git a/plonky2x/src/frontend/num/u32/gates/subtraction_u32.rs b/plonky2x/core/src/frontend/num/u32/gates/subtraction_u32.rs similarity index 100% rename from plonky2x/src/frontend/num/u32/gates/subtraction_u32.rs rename to plonky2x/core/src/frontend/num/u32/gates/subtraction_u32.rs diff --git a/plonky2x/src/frontend/num/u32/mod.rs b/plonky2x/core/src/frontend/num/u32/mod.rs similarity index 100% rename from plonky2x/src/frontend/num/u32/mod.rs rename to plonky2x/core/src/frontend/num/u32/mod.rs diff --git a/plonky2x/src/frontend/num/u32/serialization.rs b/plonky2x/core/src/frontend/num/u32/serialization.rs similarity index 100% rename from plonky2x/src/frontend/num/u32/serialization.rs rename to plonky2x/core/src/frontend/num/u32/serialization.rs diff --git a/plonky2x/src/frontend/num/u32/witness.rs b/plonky2x/core/src/frontend/num/u32/witness.rs similarity index 100% rename from plonky2x/src/frontend/num/u32/witness.rs rename to plonky2x/core/src/frontend/num/u32/witness.rs diff --git a/plonky2x/src/frontend/ops/bitwise.rs b/plonky2x/core/src/frontend/ops/bitwise.rs similarity index 100% rename from plonky2x/src/frontend/ops/bitwise.rs rename to plonky2x/core/src/frontend/ops/bitwise.rs diff --git a/plonky2x/src/frontend/ops/index.rs b/plonky2x/core/src/frontend/ops/index.rs similarity index 100% rename from plonky2x/src/frontend/ops/index.rs rename to plonky2x/core/src/frontend/ops/index.rs diff --git a/plonky2x/src/frontend/ops/math.rs b/plonky2x/core/src/frontend/ops/math.rs similarity index 100% rename from plonky2x/src/frontend/ops/math.rs rename to plonky2x/core/src/frontend/ops/math.rs diff --git a/plonky2x/src/frontend/ops/mod.rs b/plonky2x/core/src/frontend/ops/mod.rs similarity index 100% rename from plonky2x/src/frontend/ops/mod.rs rename to plonky2x/core/src/frontend/ops/mod.rs diff --git a/plonky2x/src/frontend/recursion/extension.rs b/plonky2x/core/src/frontend/recursion/extension.rs similarity index 100% rename from plonky2x/src/frontend/recursion/extension.rs rename to plonky2x/core/src/frontend/recursion/extension.rs diff --git a/plonky2x/src/frontend/recursion/fri/mod.rs b/plonky2x/core/src/frontend/recursion/fri/mod.rs similarity index 100% rename from plonky2x/src/frontend/recursion/fri/mod.rs rename to plonky2x/core/src/frontend/recursion/fri/mod.rs diff --git a/plonky2x/src/frontend/recursion/fri/proof.rs b/plonky2x/core/src/frontend/recursion/fri/proof.rs similarity index 100% rename from plonky2x/src/frontend/recursion/fri/proof.rs rename to plonky2x/core/src/frontend/recursion/fri/proof.rs diff --git a/plonky2x/src/frontend/recursion/hash.rs b/plonky2x/core/src/frontend/recursion/hash.rs similarity index 100% rename from plonky2x/src/frontend/recursion/hash.rs rename to plonky2x/core/src/frontend/recursion/hash.rs diff --git a/plonky2x/src/frontend/recursion/mod.rs b/plonky2x/core/src/frontend/recursion/mod.rs similarity index 100% rename from plonky2x/src/frontend/recursion/mod.rs rename to plonky2x/core/src/frontend/recursion/mod.rs diff --git a/plonky2x/src/frontend/recursion/polynomial.rs b/plonky2x/core/src/frontend/recursion/polynomial.rs similarity index 100% rename from plonky2x/src/frontend/recursion/polynomial.rs rename to plonky2x/core/src/frontend/recursion/polynomial.rs diff --git a/plonky2x/src/frontend/uint/mod.rs b/plonky2x/core/src/frontend/uint/mod.rs similarity index 100% rename from plonky2x/src/frontend/uint/mod.rs rename to plonky2x/core/src/frontend/uint/mod.rs diff --git a/plonky2x/src/frontend/uint/uint128.rs b/plonky2x/core/src/frontend/uint/uint128.rs similarity index 100% rename from plonky2x/src/frontend/uint/uint128.rs rename to plonky2x/core/src/frontend/uint/uint128.rs diff --git a/plonky2x/src/frontend/uint/uint256.rs b/plonky2x/core/src/frontend/uint/uint256.rs similarity index 100% rename from plonky2x/src/frontend/uint/uint256.rs rename to plonky2x/core/src/frontend/uint/uint256.rs diff --git a/plonky2x/src/frontend/uint/uint32.rs b/plonky2x/core/src/frontend/uint/uint32.rs similarity index 100% rename from plonky2x/src/frontend/uint/uint32.rs rename to plonky2x/core/src/frontend/uint/uint32.rs diff --git a/plonky2x/src/frontend/uint/uint32_n.rs b/plonky2x/core/src/frontend/uint/uint32_n.rs similarity index 100% rename from plonky2x/src/frontend/uint/uint32_n.rs rename to plonky2x/core/src/frontend/uint/uint32_n.rs diff --git a/plonky2x/src/frontend/uint/uint64.rs b/plonky2x/core/src/frontend/uint/uint64.rs similarity index 100% rename from plonky2x/src/frontend/uint/uint64.rs rename to plonky2x/core/src/frontend/uint/uint64.rs diff --git a/plonky2x/src/frontend/vars/array.rs b/plonky2x/core/src/frontend/vars/array.rs similarity index 100% rename from plonky2x/src/frontend/vars/array.rs rename to plonky2x/core/src/frontend/vars/array.rs diff --git a/plonky2x/src/frontend/vars/boolean.rs b/plonky2x/core/src/frontend/vars/boolean.rs similarity index 100% rename from plonky2x/src/frontend/vars/boolean.rs rename to plonky2x/core/src/frontend/vars/boolean.rs diff --git a/plonky2x/src/frontend/vars/byte.rs b/plonky2x/core/src/frontend/vars/byte.rs similarity index 100% rename from plonky2x/src/frontend/vars/byte.rs rename to plonky2x/core/src/frontend/vars/byte.rs diff --git a/plonky2x/src/frontend/vars/bytes.rs b/plonky2x/core/src/frontend/vars/bytes.rs similarity index 100% rename from plonky2x/src/frontend/vars/bytes.rs rename to plonky2x/core/src/frontend/vars/bytes.rs diff --git a/plonky2x/src/frontend/vars/bytes32.rs b/plonky2x/core/src/frontend/vars/bytes32.rs similarity index 100% rename from plonky2x/src/frontend/vars/bytes32.rs rename to plonky2x/core/src/frontend/vars/bytes32.rs diff --git a/plonky2x/src/frontend/vars/collections.rs b/plonky2x/core/src/frontend/vars/collections.rs similarity index 100% rename from plonky2x/src/frontend/vars/collections.rs rename to plonky2x/core/src/frontend/vars/collections.rs diff --git a/plonky2x/src/frontend/vars/mod.rs b/plonky2x/core/src/frontend/vars/mod.rs similarity index 100% rename from plonky2x/src/frontend/vars/mod.rs rename to plonky2x/core/src/frontend/vars/mod.rs diff --git a/plonky2x/src/frontend/vars/stream.rs b/plonky2x/core/src/frontend/vars/stream.rs similarity index 100% rename from plonky2x/src/frontend/vars/stream.rs rename to plonky2x/core/src/frontend/vars/stream.rs diff --git a/plonky2x/src/frontend/vars/variable.rs b/plonky2x/core/src/frontend/vars/variable.rs similarity index 100% rename from plonky2x/src/frontend/vars/variable.rs rename to plonky2x/core/src/frontend/vars/variable.rs diff --git a/plonky2x/src/lib.rs b/plonky2x/core/src/lib.rs similarity index 100% rename from plonky2x/src/lib.rs rename to plonky2x/core/src/lib.rs diff --git a/plonky2x/src/resources/Verifier.sol b/plonky2x/core/src/resources/Verifier.sol similarity index 100% rename from plonky2x/src/resources/Verifier.sol rename to plonky2x/core/src/resources/Verifier.sol diff --git a/plonky2x/src/utils/eth/beacon/mod.rs b/plonky2x/core/src/utils/eth/beacon/mod.rs similarity index 100% rename from plonky2x/src/utils/eth/beacon/mod.rs rename to plonky2x/core/src/utils/eth/beacon/mod.rs diff --git a/plonky2x/src/utils/eth/beaconchain/mod.rs b/plonky2x/core/src/utils/eth/beaconchain/mod.rs similarity index 100% rename from plonky2x/src/utils/eth/beaconchain/mod.rs rename to plonky2x/core/src/utils/eth/beaconchain/mod.rs diff --git a/plonky2x/src/utils/eth/mod.rs b/plonky2x/core/src/utils/eth/mod.rs similarity index 100% rename from plonky2x/src/utils/eth/mod.rs rename to plonky2x/core/src/utils/eth/mod.rs diff --git a/plonky2x/src/utils/hash/mod.rs b/plonky2x/core/src/utils/hash/mod.rs similarity index 100% rename from plonky2x/src/utils/hash/mod.rs rename to plonky2x/core/src/utils/hash/mod.rs diff --git a/plonky2x/src/utils/lido/mod.rs b/plonky2x/core/src/utils/lido/mod.rs similarity index 100% rename from plonky2x/src/utils/lido/mod.rs rename to plonky2x/core/src/utils/lido/mod.rs diff --git a/plonky2x/src/utils/lido/node_operators_abi.json b/plonky2x/core/src/utils/lido/node_operators_abi.json similarity index 100% rename from plonky2x/src/utils/lido/node_operators_abi.json rename to plonky2x/core/src/utils/lido/node_operators_abi.json diff --git a/plonky2x/src/utils/lido/utils.rs b/plonky2x/core/src/utils/lido/utils.rs similarity index 100% rename from plonky2x/src/utils/lido/utils.rs rename to plonky2x/core/src/utils/lido/utils.rs diff --git a/plonky2x/src/utils/mod.rs b/plonky2x/core/src/utils/mod.rs similarity index 100% rename from plonky2x/src/utils/mod.rs rename to plonky2x/core/src/utils/mod.rs diff --git a/plonky2x/src/utils/poseidon/mod.rs b/plonky2x/core/src/utils/poseidon/mod.rs similarity index 100% rename from plonky2x/src/utils/poseidon/mod.rs rename to plonky2x/core/src/utils/poseidon/mod.rs diff --git a/plonky2x/src/utils/proof/mod.rs b/plonky2x/core/src/utils/proof/mod.rs similarity index 100% rename from plonky2x/src/utils/proof/mod.rs rename to plonky2x/core/src/utils/proof/mod.rs diff --git a/plonky2x/src/utils/reqwest/mod.rs b/plonky2x/core/src/utils/reqwest/mod.rs similarity index 100% rename from plonky2x/src/utils/reqwest/mod.rs rename to plonky2x/core/src/utils/reqwest/mod.rs diff --git a/plonky2x/src/utils/serde/mod.rs b/plonky2x/core/src/utils/serde/mod.rs similarity index 100% rename from plonky2x/src/utils/serde/mod.rs rename to plonky2x/core/src/utils/serde/mod.rs diff --git a/plonky2x/src/utils/stream.rs b/plonky2x/core/src/utils/stream.rs similarity index 100% rename from plonky2x/src/utils/stream.rs rename to plonky2x/core/src/utils/stream.rs diff --git a/plonky2x-derive/Cargo.toml b/plonky2x/derive/Cargo.toml similarity index 100% rename from plonky2x-derive/Cargo.toml rename to plonky2x/derive/Cargo.toml diff --git a/plonky2x-derive/src/assert_is_valid.rs b/plonky2x/derive/src/assert_is_valid.rs similarity index 100% rename from plonky2x-derive/src/assert_is_valid.rs rename to plonky2x/derive/src/assert_is_valid.rs diff --git a/plonky2x-derive/src/constant.rs b/plonky2x/derive/src/constant.rs similarity index 100% rename from plonky2x-derive/src/constant.rs rename to plonky2x/derive/src/constant.rs diff --git a/plonky2x-derive/src/elements.rs b/plonky2x/derive/src/elements.rs similarity index 100% rename from plonky2x-derive/src/elements.rs rename to plonky2x/derive/src/elements.rs diff --git a/plonky2x-derive/src/init.rs b/plonky2x/derive/src/init.rs similarity index 100% rename from plonky2x-derive/src/init.rs rename to plonky2x/derive/src/init.rs diff --git a/plonky2x-derive/src/lib.rs b/plonky2x/derive/src/lib.rs similarity index 100% rename from plonky2x-derive/src/lib.rs rename to plonky2x/derive/src/lib.rs diff --git a/plonky2x-derive/src/value.rs b/plonky2x/derive/src/value.rs similarity index 100% rename from plonky2x-derive/src/value.rs rename to plonky2x/derive/src/value.rs diff --git a/plonky2x-derive/src/variables.rs b/plonky2x/derive/src/variables.rs similarity index 100% rename from plonky2x-derive/src/variables.rs rename to plonky2x/derive/src/variables.rs diff --git a/plonky2x-derive/src/witness.rs b/plonky2x/derive/src/witness.rs similarity index 100% rename from plonky2x-derive/src/witness.rs rename to plonky2x/derive/src/witness.rs diff --git a/plonky2x-verifier/circuit.go b/plonky2x/verifier/circuit.go similarity index 100% rename from plonky2x-verifier/circuit.go rename to plonky2x/verifier/circuit.go diff --git a/plonky2x-verifier/cli.go b/plonky2x/verifier/cli.go similarity index 100% rename from plonky2x-verifier/cli.go rename to plonky2x/verifier/cli.go diff --git a/plonky2x-verifier/prover.go b/plonky2x/verifier/prover.go similarity index 100% rename from plonky2x-verifier/prover.go rename to plonky2x/verifier/prover.go diff --git a/plonky2x-verifier/verifier.go b/plonky2x/verifier/verifier.go similarity index 100% rename from plonky2x-verifier/verifier.go rename to plonky2x/verifier/verifier.go diff --git a/plonky2x-verifier/verifier_test.go b/plonky2x/verifier/verifier_test.go similarity index 100% rename from plonky2x-verifier/verifier_test.go rename to plonky2x/verifier/verifier_test.go diff --git a/rustx/Cargo.toml b/rustx/Cargo.toml new file mode 100644 index 000000000..46f62c154 --- /dev/null +++ b/rustx/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "rustx" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[features] +default = ["parallel", "std", "timing"] +parallel = ["plonky2/parallel"] +std = ["plonky2/std"] +timing = ["plonky2/timing"] +ci = [] + +[dependencies] +alloy-primitives = "0.4.2" +alloy-sol-types = "0.4.2" +clap = "4.4.6" +dotenv = "0.15.0" +env_logger = "0.10.0" +ethers = "2.0.10" +hex = "0.4.3" +log = "0.4.20" +plonky2 = { git = "https://github.com/mir-protocol/plonky2.git", default-features = false } +plonky2x = { path = "../plonky2x/core" } +serde = "1.0.188" +serde_json = "1.0.107" +tokio = "1.33.0" + +[dev-dependencies] +plonky2 = { git = "https://github.com/mir-protocol/plonky2.git", features = [ + "gate_testing", +] } diff --git a/rustx/examples/eth_call.rs b/rustx/examples/eth_call.rs new file mode 100644 index 000000000..e4e038d15 --- /dev/null +++ b/rustx/examples/eth_call.rs @@ -0,0 +1,86 @@ +use std::env; + +use alloy_sol_types::{sol, SolType}; +use ethers::middleware::Middleware; +use ethers::providers::{Http, Provider}; +use ethers::types::transaction::eip2718::TypedTransaction; +use ethers::types::{Eip1559TransactionRequest, H160}; +use rustx::function::RustFunction; +use rustx::program::Program; + +/// The tuple which encodes an eth_call request from the EVM. +type EthCallRequestTuple = sol! { tuple(uint32, uint64, address, address, bytes) }; + +#[derive(Debug, Clone)] +struct EthCall; + +impl Program for EthCall { + fn run(input_bytes: Vec) -> Vec { + // Decode the input bytes into the request tuple. + let (chain_id, block_number, from_address, to_address, calldata) = + EthCallRequestTuple::abi_decode(&input_bytes, true).unwrap(); + + // Get relevant enviroment variables and initialize the HTTP provider. + dotenv::dotenv().ok(); + let rpc_url = env::var(format!("RPC_{}", chain_id)) + .unwrap_or_else(|_| panic!("RPC_{} environment variable was not found", chain_id)); + let provider: Provider = Provider::::try_from(rpc_url).unwrap(); + + // Construct the transaction with the decoded values. + let mut tx = Eip1559TransactionRequest::new(); + tx = tx.from::(from_address.0 .0.into()); + tx = tx.to::(to_address.0 .0.into()); + tx = tx.data(calldata); + let tx = TypedTransaction::Eip1559(tx); + + // Execute the eth_call via rpc. + let rt = tokio::runtime::Runtime::new().unwrap(); + let bytes = rt + .block_on(async { provider.call(&tx, Some(block_number.into())).await }) + .unwrap() + .0; + bytes.into() + } +} + +fn main() { + EthCall::entrypoint(); +} + +#[cfg(test)] +mod tests { + use alloy_primitives::{address, bytes}; + use hex; + + use super::*; + + #[test] + #[cfg_attr(feature = "ci", ignore)] + fn test_eth_call() { + // Construct the request. + let request = EthCallRequestTuple::abi_encode(&( + 5u32, + 9591261u64, + address!("355348b048b5b491793110bb76d7a2723262d175"), + address!("d555cd8277b0e16860f0ae44fcbc2ed94dfce9da"), + bytes!("050DDCCE00000000000000000000000003ACD25623E5999FDDC27BE7FDB904358700F3AE000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000064EB9D300000000000000000000000000000000000000000000000000000000000000000").to_vec() + )); + + // Assert that the encoding matches. + let input_hex = hex::encode(request.clone()); + assert_eq!( + input_hex, + "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000009259dd000000000000000000000000355348b048b5b491793110bb76d7a2723262d175000000000000000000000000d555cd8277b0e16860f0ae44fcbc2ed94dfce9da00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a4050ddcce00000000000000000000000003acd25623e5999fddc27be7fdb904358700f3ae000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000064eb9d30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + ); + + // Compute the output. + let output = EthCall::run(request); + + // Assert that the output matches. + let result = hex::encode(output); + assert_eq!( + result, + "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000064eb9d90000000000000000000000000000000000000000000000000000048198737bd73000000000000000000000000000000000000000000000000000000006c6f600000000000000000000000000000000000000000000000021dcea0a4ea31b41370" + ); + } +} diff --git a/rustx/src/args.rs b/rustx/src/args.rs new file mode 100644 index 000000000..7abba8e94 --- /dev/null +++ b/rustx/src/args.rs @@ -0,0 +1,31 @@ +use clap::{Parser, Subcommand}; + +#[derive(Parser, Debug, Clone)] +#[command(about = "Compile a program.")] +pub struct CompileArgs { + #[arg(long, default_value = "./build")] + pub build_dir: String, +} + +#[derive(Parser, Debug, Clone)] +#[command(about = "Run a program.")] +pub struct ProveArgs { + #[arg(long, default_value = "./build")] + pub build_dir: String, + + #[clap(long)] + pub input_json: String, +} + +#[derive(Subcommand, Debug, Clone)] +pub enum Commands { + Compile(CompileArgs), + Prove(ProveArgs), +} + +#[derive(Parser, Debug, Clone)] +#[command(about = "A tool for building and proving programs.")] +pub struct Args { + #[command(subcommand)] + pub command: Commands, +} diff --git a/rustx/src/function.rs b/rustx/src/function.rs new file mode 100644 index 000000000..674ed67cc --- /dev/null +++ b/rustx/src/function.rs @@ -0,0 +1,96 @@ +use std::fs::File; +use std::io::Write; + +use clap::Parser; +use log::info; +use plonky2x::backend::function::{ProofRequest, ProofResult}; +use plonky2x::prelude::DefaultParameters; + +use crate::args::{Args, Commands, CompileArgs}; +use crate::program::Program; + +pub trait RustFunction { + fn compile(args: CompileArgs); + + fn prove(input_json: String); + + fn entrypoint(); + + fn verifier(tx_origin: &str) -> String; +} + +impl RustFunction for P { + fn compile(args: CompileArgs) { + info!("Building verifier contract..."); + let contract_path = format!("{}/FunctionVerifier.sol", args.build_dir); + let mut contract_file = File::create(&contract_path).unwrap(); + let tx_origin = P::tx_origin(); + let verifier_contract = Self::verifier(&tx_origin); + contract_file + .write_all(verifier_contract.as_bytes()) + .unwrap(); + info!( + "Successfully saved verifier contract to disk at {}.", + contract_path + ); + } + + fn prove(input_json: String) { + info!("Loading input..."); + let proof_request = ProofRequest::::load(&input_json); + if let ProofRequest::Bytes(request) = proof_request { + let input_bytes = request.data.input; + info!("Running function..."); + let result_bytes = P::run(input_bytes); + info!("Got result bytes."); + let proof_result = + ProofResult::::from_bytes(vec![], result_bytes); + let json = serde_json::to_string_pretty(&proof_result).unwrap(); + let mut file = File::create("output.json").unwrap(); + file.write_all(json.as_bytes()).unwrap(); + info!("Successfully saved proof to disk at output.json."); + } else { + panic!("Invalid proof request type."); + } + } + + fn entrypoint() { + dotenv::dotenv().ok(); + env_logger::try_init().unwrap_or_default(); + + let args = Args::parse(); + match args.command { + Commands::Compile(args) => { + Self::compile(args); + } + Commands::Prove(args) => { + Self::prove(args.input_json); + } + } + } + + fn verifier(tx_origin: &str) -> String { + " +pragma solidity ^0.8.16; + +interface IFunctionVerifier { + function verify(bytes32 _inputHash, bytes32 _outputHash, bytes memory _proof) external view returns (bool); + + function verificationKeyHash() external pure returns (bytes32); +} + +contract FunctionVerifier is IFunctionVerifier { + + address public constant TX_ORIGIN = {TX_ORIGIN}; + + function verify(bytes32 _inputHash, bytes32 _outputHash, bytes memory _proof) external view returns (bool) { + return tx.origin == TX_ORIGIN; + } + + function verificationKeyHash() external pure returns (bytes32) { + return bytes32(0); + } +} +".replace("{TX_ORIGIN}", tx_origin) + } +} diff --git a/rustx/src/lib.rs b/rustx/src/lib.rs new file mode 100644 index 000000000..52bb65f4e --- /dev/null +++ b/rustx/src/lib.rs @@ -0,0 +1,3 @@ +pub mod args; +pub mod function; +pub mod program; diff --git a/rustx/src/program.rs b/rustx/src/program.rs new file mode 100644 index 000000000..a2c6232dd --- /dev/null +++ b/rustx/src/program.rs @@ -0,0 +1,13 @@ +use core::fmt::Debug; + +/// A trait for a program that can be verified on-chain via a trusted relayer. +pub trait Program: Debug + Clone { + /// The logic of the function in the form `f(inputBytes) -> outputBytes`. + fn run(input_bytes: Vec) -> Vec; + + /// The address of the trusted relayer. Inside the contract, we verify that + /// `tx.origin == tx_origin`. + fn tx_origin() -> String { + "0xDEd0000E32f8F40414d3ab3a830f735a3553E18e".to_string() + } +} diff --git a/scripts/abi.sh b/scripts/abi.sh deleted file mode 100644 index 200e0d989..000000000 --- a/scripts/abi.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -# exit when any command fails -set -e - -echo "Generating Contract ABIs..." - -# Clean old build artifacts -rm -rf ./out - -# forge build: outputs normal forge .json files and json files to out/ -FOUNDRY_IGNORED_ERROR_CODES='[5574,5740,1878]' forge build --contracts ./contracts --config-path ./contracts/foundry.toml --extra-output-files abi --extra-output-files evm.deployedBytecode.object --force - -echo "Generated ABI!" diff --git a/scripts/binding.sh b/scripts/binding.sh deleted file mode 100644 index 8924a4766..000000000 --- a/scripts/binding.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# exit when any command fails -set -e - -# Add to this list for each contract you want to generate bindings for. Must be in the abi folder. -CONTRACTS=(FunctionGateway FunctionRegistry StorageOracle) - -# Clear previous bindings so there is no leftovers (e.g. in case of rename). -rm -rf ./bindings/* - -echo "Generating Go Contract Bindings..." - -for contract in "${CONTRACTS[@]}"; do - echo "Generating Binding for $contract..." - forge inspect --contracts ./contracts --config-path ./contracts/foundry.toml $contract bytecode > ./contracts/out/$contract.sol/$contract.bin - abigen --abi ./contracts/out/$contract.sol/$contract.abi.json --pkg bindings --type $contract --out ./bindings/$contract.go --bin ./contracts/out/$contract.sol/$contract.bin -done diff --git a/scripts/release.sh b/scripts/release.sh deleted file mode 100644 index 0ae085bd1..000000000 --- a/scripts/release.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -set -euf -o pipefail - -if ! echo "$1" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$'; then - echo "${1} is not in MAJOR.MINOR.PATCH format" - exit 1 -fi - -# Create a new signed annotated tag for the version -git tag "v${1}" -as -m "release v${1}" - -# Create or update the "latest" tag -git tag -af "latest" -m "latest release" "v${1}^{}" - -# Create or update the "nightly" tag -git tag -af "nightly" -m "nightly release" "v${1}^{}" - -# Push all tags, which triggers the Release workflow -git push --atomic origin "v${1}" "latest" "nightly" --force diff --git a/succinctup/README.md b/succinctup/README.md deleted file mode 100644 index 1dcb259a8..000000000 --- a/succinctup/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# `succinctup` - -Update or revert to a specific Succinct branch with ease. - -## Installing - -```sh -curl -L https://cli.succinct.xyz | bash -``` - -## Usage - -To install the **nightly** version: - -```sh -succinctup -``` - -To install a specific **version** (in this case the `nightly` version): - -```sh -succinctup --version nightly -``` - -To install a specific **branch** (in this case the `release/0.1.0` branch's latest commit): - -```sh -succinctup --branch release/0.1.0 -``` - -To install a **fork's main branch** (in this case `puma314/succinct`'s main branch): - -```sh -succinctup --repo puma314/succinct -``` - -To install a **specific branch in a fork** (in this case the `patch-10` branch's latest commit in `puma314/succinct`): - -```sh -succinctup --repo puma314/succinct --branch patch-10 -``` - -To install from a **specific Pull Request**: - -```sh -succinctup --pr 1071 -``` - -To install from a **specific commit**: - -```sh -succinctup -C 94bfdb2 -``` - -To install a local directory or repository (e.g. one located at `~/git/succinct`, assuming you're in the home directory) - -##### Note: --branch, --repo, and --version flags are ignored during local installations. - -```sh -succinctup --path ./git/succinct -``` - ---- - -**Tip**: All flags have a single character shorthand equivalent! You can use `-v` instead of `--version`, etc. - ---- - -## Acknowledgements - -`succinctup` based on the [Foundry](https://github.com/foundry-rs/foundry) project's installation and usage. [Foundry](https://github.com/foundry-rs/foundry) is a Rust Ethereum -client focused on performance and reliability. Big shoutout to the folks behind `foundryup` for -providing and inspiring great CLI experiences. \ No newline at end of file diff --git a/succinctup/install b/succinctup/install deleted file mode 100755 index 66c49102c..000000000 --- a/succinctup/install +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env bash -set -e - -###################################### -### succinctup installation script ### -###################################### - -# Inspired by Foundry installation: https://book.getfoundry.sh/ -echo Installing succinctup... - -BASE_DIR=${XDG_CONFIG_HOME:-$HOME} -SUCCINCT_DIR=${SUCCINCT_DIR-"$BASE_DIR/.succinct"} -SUCCINCT_BIN_DIR="$SUCCINCT_DIR/bin" -SUCCINCT_MAN_DIR="$SUCCINCT_DIR/share/man/man1" - -BIN_URL="https://cli.succinct.xyz/succinctlabs/sdk/main/succinctup/succinctup" -BIN_PATH="$SUCCINCT_BIN_DIR/succinctup" - -# Create the .succinct bin directory and succinctup binary if it doesn't exist. -mkdir -p $SUCCINCT_BIN_DIR - -# Download the succinctup binary and make it executable. -rm -rf $BIN_PATH -curl -sS -L $BIN_URL -o $BIN_PATH -chmod +x $BIN_PATH - -# Create the man directory for future man files if it doesn't exist. -mkdir -p $SUCCINCT_MAN_DIR - -# Store the correct profile file (i.e. .profile for bash or .zshenv for ZSH). -case $SHELL in -*/zsh) - PROFILE=${ZDOTDIR-"$HOME"}/.zshenv - PREF_SHELL=zsh - ;; -*/bash) - PROFILE=$HOME/.bashrc - PREF_SHELL=bash - ;; -*/fish) - PROFILE=$HOME/.config/fish/config.fish - PREF_SHELL=fish - ;; -*/ash) - PROFILE=$HOME/.profile - PREF_SHELL=ash - ;; -*) - echo "succinctup: could not detect shell, manually add ${SUCCINCT_BIN_DIR} to your PATH." - exit 1 -esac - -# Only add succinctup if it isn't already in PATH. -if [[ ":$PATH:" != *":${SUCCINCT_BIN_DIR}:"* ]]; then - # Add the succinctup directory to the path and ensure the old PATH variables remain. - echo >> $PROFILE && echo "export PATH=\"\$PATH:$SUCCINCT_BIN_DIR\"" >> $PROFILE -fi - -# Warn MacOS users that they may need to manually install libusb via Homebrew: -if [[ "$OSTYPE" =~ ^darwin ]] && [[ ! -f /usr/local/opt/libusb/lib/libusb-1.0.0.dylib && ! -f /opt/homebrew/opt/libusb/lib/libusb-1.0.0.dylib ]]; then - echo && echo "warning: libusb not found. You may need to install it manually on MacOS via Homebrew (brew install libusb)." -fi - -echo "Detected your preferred shell is ${PREF_SHELL} and added succinctup to PATH. Run 'source ${PROFILE}' or start a new terminal session to use succinctup." -echo "Then, simply run 'succinctup' to install." diff --git a/succinctup/succinctup b/succinctup/succinctup deleted file mode 100755 index 3c0d5ffd6..000000000 --- a/succinctup/succinctup +++ /dev/null @@ -1,322 +0,0 @@ -#!/usr/bin/env bash -set -e - -###################################### -###### succinctup update script ###### -###################################### - -BASE_DIR=${XDG_CONFIG_HOME:-$HOME} -SUCCINCT_DIR=${SUCCINCT_DIR:-"$BASE_DIR/.succinct"} -SUCCINCT_BIN_DIR="$SUCCINCT_DIR/bin" -SUCCINCT_MAN_DIR="$SUCCINCT_DIR/share/man/man1" - -main() { - need_cmd git - need_cmd curl - - while [[ $1 ]]; do - case $1 in - --) shift; break;; - -r|--repo) shift; SUCCINCTUP_REPO=$1;; - -b|--branch) shift; SUCCINCTUP_BRANCH=$1;; - -v|--version) shift; SUCCINCTUP_VERSION=$1;; - -p|--path) shift; SUCCINCTUP_LOCAL_REPO=$1;; - -P|--pr) shift; SUCCINCTUP_PR=$1;; - -C|--commit) shift; SUCCINCTUP_COMMIT=$1;; - -h|--help) - usage - exit 0 - ;; - *) - warn "unknown option: $1" - usage - exit 1 - esac; shift - done - - # Print the banner after successfully parsing args - banner - - if [ -n "$SUCCINCTUP_PR" ]; then - if [ -z "$SUCCINCTUP_BRANCH" ]; then - SUCCINCTUP_BRANCH="refs/pull/$SUCCINCTUP_PR/head" - else - err "can't use --pr and --branch at the same time" - fi - fi - - # Installs succinct from a local repository if --path parameter is provided - if [[ -n "$SUCCINCTUP_LOCAL_REPO" ]]; then - need_cmd go - - # Ignore branches/versions as we do not want to modify local git state - if [ -n "$SUCCINCTUP_REPO" ] || [ -n "$SUCCINCTUP_BRANCH" ] || [ -n "$SUCCINCTUP_VERSION" ]; then - warn "--branch, --version, and --repo arguments are ignored during local install" - fi - - # Enter local repo and build - say "installing from $SUCCINCTUP_LOCAL_REPO" - cd "$SUCCINCTUP_LOCAL_REPO/cli" - ensure go build -o "$SUCCINCT_BIN_DIR/succinct" main.go - - say "done" - exit 0 - fi - - SUCCINCTUP_REPO=${SUCCINCTUP_REPO:-succinctlabs/sdk} - - # Install by downloading binaries - if [[ "$SUCCINCTUP_REPO" == "succinctlabs/sdk" && -z "$SUCCINCTUP_BRANCH" && -z "$SUCCINCTUP_COMMIT" ]]; then - SUCCINCTUP_VERSION=${SUCCINCTUP_VERSION:-nightly} - SUCCINCTUP_TAG=$SUCCINCTUP_VERSION - - # Normalize versions (handle channels, versions without v prefix - if [[ "$SUCCINCTUP_VERSION" == "nightly" ]]; then - # Locate real nightly tag - # SHA=$(ensure curl -sSf "https://cli.succinct.xyz/repos/$SUCCINCTUP_REPO/git/refs/tags/nightly" \ - # | grep -Eo '"sha"[^,]*' \ - # | grep -Eo '[^:]*$' \ - # | tr -d '"' \ - # | tr -d ' ' \ - # | cut -d ':' -f2 ) - # SUCCINCTUP_TAG="nightly-${SHA}" - SUCCINCTUP_TAG="nightly" - elif [[ "$SUCCINCTUP_VERSION" == nightly* ]]; then - SUCCINCTUP_VERSION="nightly" - elif [[ "$SUCCINCTUP_VERSION" == [[:digit:]]* ]]; then - # Add v prefix - SUCCINCTUP_VERSION="v${SUCCINCTUP_VERSION}" - SUCCINCTUP_TAG="${SUCCINCTUP_VERSION}" - fi - - say "installing succinct (version ${SUCCINCTUP_VERSION}, tag ${SUCCINCTUP_TAG})" - - PLATFORM="$(uname -s)" - EXT="tar.gz" - case $PLATFORM in - Linux) - PLATFORM="linux" - ;; - Darwin) - PLATFORM="darwin" - ;; - MINGW*) - EXT="zip" - PLATFORM="win32" - ;; - *) - err "unsupported platform: $PLATFORM" - ;; - esac - - ARCHITECTURE="$(uname -m)" - if [ "${ARCHITECTURE}" = "x86_64" ]; then - # Redirect stderr to /dev/null to avoid printing errors if non Rosetta. - if [ "$(sysctl -n sysctl.proc_translated 2>/dev/null)" = "1" ]; then - ARCHITECTURE="arm64" # Rosetta. - else - ARCHITECTURE="amd64" # Intel. - fi - elif [ "${ARCHITECTURE}" = "arm64" ] ||[ "${ARCHITECTURE}" = "aarch64" ] ; then - ARCHITECTURE="arm64" # Arm. - else - ARCHITECTURE="amd64" # Amd. - fi - - # Compute the URL of the release tarball in the Succinct repository. - RELEASE_URL="https://cli.succinct.xyz/repos/${SUCCINCTUP_REPO}/tarball/${SUCCINCTUP_TAG}" - - # Check if the SUCCINCT_BIN_DIR exists and remove it if it does - if [ -d "$SUCCINCT_BIN_DIR" ]; then - say "Removing existing directory $SUCCINCT_BIN_DIR" - rm -rf "$SUCCINCT_BIN_DIR" - fi - - # Ensure the directory exists - ensure mkdir -p "$SUCCINCT_BIN_DIR" - - # Download and extract the binaries archive - say "downloading latest succinct binaries from $RELEASE_URL..." - tmp_file="$(mktemp -t succinct.tar.gz)" - # Use wget with the GitHub API to download the tarball, suppress output with -q - ensure wget -q -O "$tmp_file" "$RELEASE_URL" >/dev/null 2>&1 - file "$tmp_file" # Print the file type - tmp_dir="$(mktemp -d -t succinct)" - ensure tar -xzC "$tmp_dir" -f "$tmp_file" - # Move the content from the top-level directory to the desired location - ensure mv "$tmp_dir"/*/* "$SUCCINCT_BIN_DIR" - rm -rf "$tmp_file" - rm -rf "$tmp_dir" - - say "download successful, building the CLI..." - - # Build the CLI and move it to the bin directory with it named as "succinct". - cli_dir="$SUCCINCT_BIN_DIR/cli" - ensure cd "$cli_dir" - ensure go build - ensure mv "$cli_dir/cli" "$SUCCINCT_BIN_DIR/succinct" - - # Optionally download the manuals - # if check_cmd tar; then - # say "downloading manpages" - # mkdir -p "$SUCCINCT_MAN_DIR" - # download "$MAN_TARBALL_URL" | tar -xzC "$SUCCINCT_MAN_DIR" - # else - # say 'skipping manpage download: missing "tar"' - # fi - - bin_path="$SUCCINCT_BIN_DIR/succinct" - - # Print installed msg TODO when --version flag works - # say "installed - $(ensure "$bin_path" --version)" - - # Check if the default path of the binary is not in SUCCINCT_BIN_DIR - which_path="$(which succinct)" - if [ "$which_path" != "$bin_path" ]; then - warn "" - cat 1>&2 < "$SUCCINCT_MAN_DIR/$bin.1" - # done - # fi - - say "done" - fi -} - -usage() { - cat 1>&2 < - -OPTIONS: - -h, --help Print help information - -v, --version Install a specific version - -b, --branch Install a specific branch - -P, --pr Install a specific Pull Request - -C, --commit Install a specific commit - -r, --repo Install from a remote GitHub repo (uses default branch if no other options are set) - -p, --path Install a local repository -EOF -} - -say() { - printf "succinctup: %s\n" "$1" -} - -warn() { - say "warning: ${1}" >&2 -} - -err() { - say "$1" >&2 - exit 1 -} - -need_cmd() { - if ! check_cmd "$1"; then - err "need '$1' (command not found)" - fi -} - -check_cmd() { - command -v "$1" &>/dev/null -} - -# Run a command that should never fail. If the command fails execution -# will immediately terminate with an error showing the failing -# command. -ensure() { - if ! "$@"; then err "command failed: $*"; fi -} - -# Downloads $1 into $2 or stdout -download() { - if [ "$2" ]; then - # output into $2 - if check_cmd curl; then - curl -#o "$2" -L "$1" - else - wget --show-progress -qO "$2" "$1" - fi - else - # output to stdout - if check_cmd curl; then - curl -#L "$1" - else - wget --show-progress -qO- "$1" - fi - fi -} - -# Banner Function for Succinct -banner() { - printf ' - -############################################################### - - ██████╗██╗ ██╗ █████╗ █████╗ ██╗███╗ ██╗ █████╗ ████████╗ -██╔════╝██║ ██║██╔══██╗██╔══██╗██║████╗ ██║██╔══██╗╚══██╔══╝ -╚█████╗ ██║ ██║██║ ╚═╝██║ ╚═╝██║██╔██╗██║██║ ╚═╝ ██║ - ╚═══██╗██║ ██║██║ ██╗██║ ██╗██║██║╚████║██║ ██╗ ██║ -██████╔╝╚██████╔╝╚█████╔╝╚█████╔╝██║██║ ╚███║╚█████╔╝ ██║ -╚═════╝ ╚═════╝ ╚════╝ ╚════╝ ╚═╝╚═╝ ╚══╝ ╚════╝ ╚═╝ - -############################################################### - -Repo : https://github.com/succinctlabs/sdk -Discord : https://discord.gg/succinctlabs -Twitter : https://twitter.com/succinctlabs - -############################################################### - -' -} - -main "$@" || exit 1 From fcdec71551b912391ac6af199b80a8916ca7613b Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 9 Oct 2023 16:32:29 -0700 Subject: [PATCH 02/19] feat: cleanup --- plonky2x/core/src/backend/function/args.rs | 4 ++-- plonky2x/core/src/backend/function/mod.rs | 10 +++++----- rustx/examples/eth_call.json | 7 +++++++ rustx/examples/eth_call.rs | 16 ++++++++++++++++ rustx/src/args.rs | 9 ++++----- rustx/src/function.rs | 14 +++++++------- 6 files changed, 41 insertions(+), 19 deletions(-) create mode 100644 rustx/examples/eth_call.json diff --git a/plonky2x/core/src/backend/function/args.rs b/plonky2x/core/src/backend/function/args.rs index 7f6c9dafc..77c1695b3 100644 --- a/plonky2x/core/src/backend/function/args.rs +++ b/plonky2x/core/src/backend/function/args.rs @@ -2,7 +2,7 @@ use clap::{Parser, Subcommand}; #[derive(Parser, Debug, Clone)] #[command(about = "Compile a circuit.")] -pub struct CompileArgs { +pub struct BuildArgs { #[arg(long, default_value = "./build")] pub build_dir: String, } @@ -23,7 +23,7 @@ pub struct ProveArgs { #[derive(Subcommand, Debug, Clone)] pub enum Commands { - Compile(CompileArgs), + Build(BuildArgs), Prove(ProveArgs), } diff --git a/plonky2x/core/src/backend/function/mod.rs b/plonky2x/core/src/backend/function/mod.rs index 3ffb65a50..f4efeadef 100644 --- a/plonky2x/core/src/backend/function/mod.rs +++ b/plonky2x/core/src/backend/function/mod.rs @@ -15,7 +15,7 @@ pub use result::*; use serde::Serialize; use sha2::Digest; -use self::args::{CompileArgs, ProveArgs}; +use self::args::{BuildArgs, ProveArgs}; use crate::backend::circuit::*; use crate::backend::function::args::{Args, Commands}; use crate::backend::wrapper::wrap::WrappedCircuit; @@ -27,7 +27,7 @@ const VERIFIER_CONTRACT: &str = include_str!("../../resources/Verifier.sol"); /// `Plonky2xFunction`s have all necessary code for a circuit to be deployed end-to-end. pub trait Plonky2xFunction { /// Builds the circuit and saves it to disk. - fn compile, const D: usize>(args: CompileArgs) + fn build, const D: usize>(args: BuildArgs) where <>::Config as GenericConfig>::Hasher: AlgebraicHasher; @@ -52,7 +52,7 @@ pub trait Plonky2xFunction { } impl Plonky2xFunction for C { - fn compile, const D: usize>(args: CompileArgs) + fn build, const D: usize>(args: BuildArgs) where <>::Config as GenericConfig>::Hasher: AlgebraicHasher, { @@ -227,8 +227,8 @@ impl Plonky2xFunction for C { let args = Args::parse(); match args.command { - Commands::Compile(args) => { - Self::compile::(args); + Commands::Build(args) => { + Self::build::(args); } Commands::Prove(args) => { let request = ProofRequest::::load(&args.input_json); diff --git a/rustx/examples/eth_call.json b/rustx/examples/eth_call.json new file mode 100644 index 000000000..1f2e86dd8 --- /dev/null +++ b/rustx/examples/eth_call.json @@ -0,0 +1,7 @@ +{ + "type": "req_bytes", + "releaseId": "", + "data": { + "input": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000009259dd000000000000000000000000355348b048b5b491793110bb76d7a2723262d175000000000000000000000000d555cd8277b0e16860f0ae44fcbc2ed94dfce9da00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a4050ddcce00000000000000000000000003acd25623e5999fddc27be7fdb904358700f3ae000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000064eb9d30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } +} \ No newline at end of file diff --git a/rustx/examples/eth_call.rs b/rustx/examples/eth_call.rs index e4e038d15..fb42f9893 100644 --- a/rustx/examples/eth_call.rs +++ b/rustx/examples/eth_call.rs @@ -1,3 +1,19 @@ +//! An example of a basic EVM function which takes in on-chain input bytes and returns output bytes +//! that correspond to the result of an `eth_call`. +//! +//! To build the binary: +//! +//! `cargo build --example eth_call --release` +//! +//! To build the function, which saves the verifier contract: +//! +//! `./target/release/example/eth_call build` +//! +//! To generate the output and proof: +//! +//! `./target/release/example/eth_call prove --input-json input.json` +//! + use std::env; use alloy_sol_types::{sol, SolType}; diff --git a/rustx/src/args.rs b/rustx/src/args.rs index 7abba8e94..7f6383ba1 100644 --- a/rustx/src/args.rs +++ b/rustx/src/args.rs @@ -2,7 +2,7 @@ use clap::{Parser, Subcommand}; #[derive(Parser, Debug, Clone)] #[command(about = "Compile a program.")] -pub struct CompileArgs { +pub struct BuildArgs { #[arg(long, default_value = "./build")] pub build_dir: String, } @@ -10,16 +10,15 @@ pub struct CompileArgs { #[derive(Parser, Debug, Clone)] #[command(about = "Run a program.")] pub struct ProveArgs { + pub input_json: String, + #[arg(long, default_value = "./build")] pub build_dir: String, - - #[clap(long)] - pub input_json: String, } #[derive(Subcommand, Debug, Clone)] pub enum Commands { - Compile(CompileArgs), + Build(BuildArgs), Prove(ProveArgs), } diff --git a/rustx/src/function.rs b/rustx/src/function.rs index 674ed67cc..19d2e67ad 100644 --- a/rustx/src/function.rs +++ b/rustx/src/function.rs @@ -6,11 +6,11 @@ use log::info; use plonky2x::backend::function::{ProofRequest, ProofResult}; use plonky2x::prelude::DefaultParameters; -use crate::args::{Args, Commands, CompileArgs}; +use crate::args::{Args, BuildArgs, Commands}; use crate::program::Program; pub trait RustFunction { - fn compile(args: CompileArgs); + fn build(args: BuildArgs); fn prove(input_json: String); @@ -20,7 +20,7 @@ pub trait RustFunction { } impl RustFunction for P { - fn compile(args: CompileArgs) { + fn build(args: BuildArgs) { info!("Building verifier contract..."); let contract_path = format!("{}/FunctionVerifier.sol", args.build_dir); let mut contract_file = File::create(&contract_path).unwrap(); @@ -60,8 +60,8 @@ impl RustFunction for P { let args = Args::parse(); match args.command { - Commands::Compile(args) => { - Self::compile(args); + Commands::Build(args) => { + Self::build(args); } Commands::Prove(args) => { Self::prove(args.input_json); @@ -70,7 +70,7 @@ impl RustFunction for P { } fn verifier(tx_origin: &str) -> String { - " + "// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; interface IFunctionVerifier { @@ -83,7 +83,7 @@ contract FunctionVerifier is IFunctionVerifier { address public constant TX_ORIGIN = {TX_ORIGIN}; - function verify(bytes32 _inputHash, bytes32 _outputHash, bytes memory _proof) external view returns (bool) { + function verify(bytes32, bytes32, bytes memory) external view returns (bool) { return tx.origin == TX_ORIGIN; } From cdfabf22cc23704028ee140188534a4b6663649c Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 9 Oct 2023 16:38:15 -0700 Subject: [PATCH 03/19] feat: schema.json --- schema.json | 32 ++++++++++++++++++++++++++++++++ succinct.json | 14 ++++++++++---- 2 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 schema.json diff --git a/schema.json b/schema.json new file mode 100644 index 000000000..a177f0914 --- /dev/null +++ b/schema.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "entrypoints": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "framework": { + "type": "string", + "enum": ["rustx", "gnarkx", "circomx", "plonky2x"] + }, + "baseDir": { + "type": "string" + }, + "buildCommand": { + "type": "string" + }, + "proveCommand": { + "type": "string" + } + }, + "required": ["name", "framework", "baseDir", "buildCommand", "proveCommand"] + } + } + }, + "required": ["entrypoints"] +} \ No newline at end of file diff --git a/succinct.json b/succinct.json index 52fe9fa7e..0217b04c4 100644 --- a/succinct.json +++ b/succinct.json @@ -1,5 +1,11 @@ { - "preset": "plonky2", - "build_command": "rm -rf ./build && mkdir build && rustup override set nightly && RUST_LOG=debug cargo run --release --example mapreduce_validators build && cp ./target/release/examples/mapreduce_validators ./build/mapreduce_validators", - "prove_command": "RUST_LOG=debug ./build/mapreduce_validators prove --input-json input.json" -} + "entrypoints": [ + { + "name": "eth_call", + "framework": "succinctx", + "baseDir": ".", + "buildCommand": "cargo run --release --example eth_call build && mv ./target/release/examples/eth_call ./build/eth_call", + "proveCommand": "./build/eth_call prove input.json" + } + ] +} \ No newline at end of file From 5b2653e25cb452da209a9f168d3e23a3321b2262 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 9 Oct 2023 16:40:59 -0700 Subject: [PATCH 04/19] feat: schema.json --- .github/workflows/release.yml | 49 ----------------------------------- 1 file changed, 49 deletions(-) delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 9e24e9819..000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Go Release - -on: - push: - branches-ignore: - - "**" - tags: - - "v*.*.*" - -permissions: - contents: write - packages: write - -jobs: - test: - name: Release - runs-on: chad - - steps: - - name: Checkout repo - uses: actions/checkout@v3 - with: - submodules: recursive - token: ${{ secrets.PRIVATE_PULL_TOKEN }} - - - name: Setup Go - uses: actions/setup-go@v3 - with: - go-version: "1.20" - - - name: Login to GitHub Container Registry - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u succinctlabs --password-stdin - - # - name: Import GPG key - # id: import_gpg - # uses: crazy-max/ghaction-import-gpg@v5 - # with: - # gpg_private_key: ${{ secrets.GPG_SIGNING_KEY }} - # passphrase: ${{ secrets.GPG_PASSPHRASE }} - # - - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v4 - with: - distribution: goreleaser - version: latest - args: release --clean - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} From 20c1fb2ac06947be1122570712859ab3dd6057b1 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 9 Oct 2023 16:41:37 -0700 Subject: [PATCH 05/19] feat: schema.json --- succinct.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/succinct.json b/succinct.json index 0217b04c4..050903a15 100644 --- a/succinct.json +++ b/succinct.json @@ -4,7 +4,7 @@ "name": "eth_call", "framework": "succinctx", "baseDir": ".", - "buildCommand": "cargo run --release --example eth_call build && mv ./target/release/examples/eth_call ./build/eth_call", + "buildCommand": "mkdir build && cargo run --release --example eth_call build && mv ./target/release/examples/eth_call ./build/eth_call", "proveCommand": "./build/eth_call prove input.json" } ] From 548695ce328f01a88d0929d9da4f0b4496ed0213 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 9 Oct 2023 16:47:21 -0700 Subject: [PATCH 06/19] feat: assets --- .gitignore | 3 +-- {plonky2x/core/src/resources => assets}/Verifier.sol | 0 schema.json => assets/schema.json | 0 plonky2x/core/src/backend/function/mod.rs | 2 +- 4 files changed, 2 insertions(+), 3 deletions(-) rename {plonky2x/core/src/resources => assets}/Verifier.sol (100%) rename schema.json => assets/schema.json (100%) diff --git a/.gitignore b/.gitignore index 0b574af8a..bd8b2b954 100644 --- a/.gitignore +++ b/.gitignore @@ -22,7 +22,6 @@ keystore **/__pycache__ **/FunctionVerifier.sol - .idea/ proof.json -output.json +output.json \ No newline at end of file diff --git a/plonky2x/core/src/resources/Verifier.sol b/assets/Verifier.sol similarity index 100% rename from plonky2x/core/src/resources/Verifier.sol rename to assets/Verifier.sol diff --git a/schema.json b/assets/schema.json similarity index 100% rename from schema.json rename to assets/schema.json diff --git a/plonky2x/core/src/backend/function/mod.rs b/plonky2x/core/src/backend/function/mod.rs index f4efeadef..548436590 100644 --- a/plonky2x/core/src/backend/function/mod.rs +++ b/plonky2x/core/src/backend/function/mod.rs @@ -22,7 +22,7 @@ use crate::backend::wrapper::wrap::WrappedCircuit; use crate::frontend::builder::CircuitIO; use crate::prelude::{CircuitBuilder, GateRegistry, HintRegistry}; -const VERIFIER_CONTRACT: &str = include_str!("../../resources/Verifier.sol"); +const VERIFIER_CONTRACT: &str = include_str!("../../../../../assets/Verifier.sol"); /// `Plonky2xFunction`s have all necessary code for a circuit to be deployed end-to-end. pub trait Plonky2xFunction { From 7f05370c79478ef6f17daf507eba606c8aec039e Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 9 Oct 2023 16:49:51 -0700 Subject: [PATCH 07/19] feat: assets --- plonky2x/core/examples/mapreduce_balances.rs | 130 ------------- .../core/examples/mapreduce_validators.rs | 174 ------------------ succinct.json | 9 +- 3 files changed, 8 insertions(+), 305 deletions(-) delete mode 100644 plonky2x/core/examples/mapreduce_balances.rs delete mode 100644 plonky2x/core/examples/mapreduce_validators.rs diff --git a/plonky2x/core/examples/mapreduce_balances.rs b/plonky2x/core/examples/mapreduce_balances.rs deleted file mode 100644 index 75f76687c..000000000 --- a/plonky2x/core/examples/mapreduce_balances.rs +++ /dev/null @@ -1,130 +0,0 @@ -use itertools::Itertools; -use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; -use plonky2x::backend::circuit::{Circuit, DefaultSerializer, PlonkParameters}; -use plonky2x::backend::function::Plonky2xFunction; -use plonky2x::frontend::eth::beacon::vars::BeaconBalancesVariable; -use plonky2x::frontend::mapreduce::generator::MapReduceGenerator; -use plonky2x::frontend::uint::uint64::U64Variable; -use plonky2x::prelude::{Bytes32Variable, CircuitBuilder, HintRegistry}; -use plonky2x::utils::bytes32; - -/// An example source block root. -const BLOCK_ROOT: &str = "0x4f1dd351f11a8350212b534b3fca619a2a95ad8d9c16129201be4a6d73698adb"; - -/// The number of balances to fetch. -const NB_BALANCES: usize = 1048576; - -/// The batch size for fetching balances and computing the local balance roots. -const BATCH_SIZE: usize = 2048; - -#[derive(Debug, Clone)] -struct MapReduceBalanceCircuit; - -impl Circuit for MapReduceBalanceCircuit { - fn define, const D: usize>(builder: &mut CircuitBuilder) - where - <>::Config as GenericConfig>::Hasher: - AlgebraicHasher<>::Field>, - { - let block_root = builder.constant::(bytes32!(BLOCK_ROOT)); - let partial_balances = builder.beacon_get_partial_balances::(block_root); - let idxs = (0..NB_BALANCES).map(|idx| idx as u64).collect_vec(); - - let output = builder - .mapreduce::( - partial_balances, - idxs, - |balances_root, idxs, builder| { - // Witness balances. - let balances = - builder.beacon_witness_balance_batch::(balances_root, idxs[0]); - - // Convert balances to leafs. - let mut leafs = Vec::new(); - let mut sum = builder.constant::(0); - for i in 0..idxs.len() / 4 { - let b = [ - balances[i * 4], - balances[i * 4 + 1], - balances[i * 4 + 2], - balances[i * 4 + 3] - ]; - sum = builder.add_many(&b); - leafs.push(builder.beacon_u64s_to_leaf(b)); - } - - // Reduce leafs to a single root. - while leafs.len() != 1 { - let mut tmp = Vec::new(); - for i in 0..leafs.len() / 2 { - tmp.push(builder.curta_sha256_pair(leafs[i*2], leafs[i*2+1])); - } - leafs = tmp; - } - - (leafs[0], sum) - }, - |_, left, right, builder| { - // Reduce two roots to a single root and compute the sum of the two balances. - (builder.sha256_pair(left.0, right.0), builder.add(left.1, right.1)) - } - ); - - builder.assert_is_equal(output.0, partial_balances.root); - builder.watch(&output.1, "total balance"); - builder.write(output); - } - - fn register_generators, const D: usize>(registry: &mut HintRegistry) - where - <>::Config as GenericConfig>::Hasher: AlgebraicHasher, - { - let id = MapReduceGenerator::< - L, - BeaconBalancesVariable, - U64Variable, - (Bytes32Variable, U64Variable), - Self, - BATCH_SIZE, - D, - >::id(); - registry.register_simple::>(id); - } -} - -fn main() { - MapReduceBalanceCircuit::entrypoint(); -} - -#[cfg(test)] -mod tests { - use plonky2x::prelude::DefaultParameters; - - use super::*; - - type L = DefaultParameters; - const D: usize = 2; - - #[test] - fn test_circuit() { - env_logger::try_init().unwrap_or_default(); - - let mut builder = CircuitBuilder::::new(); - MapReduceBalanceCircuit::define(&mut builder); - let circuit = builder.build(); - - let input = circuit.input(); - let (proof, output) = circuit.prove(&input); - circuit.verify(&proof, &input, &output); - - MapReduceBalanceCircuit::test_serialization::(); - } -} diff --git a/plonky2x/core/examples/mapreduce_validators.rs b/plonky2x/core/examples/mapreduce_validators.rs deleted file mode 100644 index 12a3b93f4..000000000 --- a/plonky2x/core/examples/mapreduce_validators.rs +++ /dev/null @@ -1,174 +0,0 @@ -#![allow(clippy::needless_range_loop)] - -use itertools::Itertools; -use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; -use plonky2x::backend::circuit::{Circuit, DefaultSerializer, PlonkParameters}; -use plonky2x::backend::function::Plonky2xFunction; -use plonky2x::frontend::eth::beacon::vars::{BeaconBalancesVariable, BeaconValidatorsVariable}; -use plonky2x::frontend::mapreduce::generator::MapReduceGenerator; -use plonky2x::frontend::uint::uint64::U64Variable; -use plonky2x::prelude::{Bytes32Variable, CircuitBuilder, HintRegistry}; -use plonky2x::utils::bytes32; - -// The withdrawal credentials of Lido validators. -const LIDO_WITHDRAWAL_CREDENTIALS: &str = - "0x010000000000000000000000b9d7934878b5fb9610b3fe8a5e441e8fad7e293f"; - -/// An example source block root. -const BLOCK_ROOT: &str = "0x4f1dd351f11a8350212b534b3fca619a2a95ad8d9c16129201be4a6d73698adb"; - -/// The number of balances to fetch. -const NB_VALIDATORS: usize = 131072; - -/// The batch size for fetching balances and computing the local balance roots. -const BATCH_SIZE: usize = 512; - -#[derive(Debug, Clone)] -struct MapReduceValidatorCircuit; - -impl Circuit for MapReduceValidatorCircuit { - fn define, const D: usize>(builder: &mut CircuitBuilder) - where - <>::Config as GenericConfig>::Hasher: - AlgebraicHasher<>::Field>, - { - let block_root = builder.constant::(bytes32!(BLOCK_ROOT)); - let partial_validators = builder.beacon_get_partial_validators::(block_root); - let partial_balances = builder.beacon_get_partial_balances::(block_root); - let idxs = (0..NB_VALIDATORS).map(|idx| idx as u64).collect_vec(); - - let output = builder.mapreduce::< - (BeaconValidatorsVariable, BeaconBalancesVariable), - U64Variable, - (Bytes32Variable, Bytes32Variable, U64Variable), - DefaultSerializer, - BATCH_SIZE, - _, - _, - >( - (partial_validators, partial_balances), - idxs, - |(validators_root, balances_root), idxs, builder| { - // Witness validators. - let (validator_roots, validators) = - builder.beacon_witness_compressed_validator_batch::( - validators_root, - idxs[0] - ); - - // Witness balances. - let balances = builder.beacon_witness_balance_batch::( - balances_root, - idxs[0] - ); - - // Convert validators to leafs. - let lido_withdrawal_credentials = builder.constant::( - bytes32!(LIDO_WITHDRAWAL_CREDENTIALS) - ); - let mut validator_leafs = Vec::new(); - let mut is_lido_validator = Vec::new(); - for i in 0..validators.len() { - validator_leafs.push(validator_roots[i]); - is_lido_validator.push(builder.is_equal( - validators[i].withdrawal_credentials, - lido_withdrawal_credentials - )); - } - - // Convert balances to leafs. - let mut balance_leafs = Vec::new(); - let zero = builder.constant::(0); - let mut sum = builder.constant::(0); - for i in 0..idxs.len() / 4 { - let balances = [ - balances[i*4], - balances[i*4+1], - balances[i*4+2], - balances[i*4+3], - ]; - let masked_balances = [ - builder.select(is_lido_validator[i*4], balances[0], zero), - builder.select(is_lido_validator[i*4+1], balances[1], zero), - builder.select(is_lido_validator[i*4+2], balances[2], zero), - builder.select(is_lido_validator[i*4+3], balances[3], zero), - ]; - sum = builder.add_many(&masked_balances); - balance_leafs.push(builder.beacon_u64s_to_leaf(balances)); - } - - // Reduce validator leafs to a single root. - let validators_acc = builder.ssz_hash_leafs(&validator_leafs); - let balances_acc = builder.ssz_hash_leafs(&balance_leafs); - - // Return the respective accumulators and partial sum. - (validators_acc, balances_acc, sum) - }, - |_, left, right, builder| { - ( - builder.sha256_pair(left.0, right.0), - builder.sha256_pair(left.1, right.1), - builder.add(left.2, right.2) - ) - } - ); - - builder.assert_is_equal(output.0, partial_validators.validators_root); - builder.assert_is_equal(output.1, partial_balances.root); - builder.watch(&output.2, "total balance"); - } - - fn register_generators, const D: usize>(registry: &mut HintRegistry) - where - <>::Config as GenericConfig>::Hasher: AlgebraicHasher, - { - let id = MapReduceGenerator::< - L, - (BeaconValidatorsVariable, BeaconBalancesVariable), - U64Variable, - (Bytes32Variable, Bytes32Variable, U64Variable), - Self, - BATCH_SIZE, - D, - >::id(); - registry.register_simple::>(id); - } -} - -fn main() { - MapReduceValidatorCircuit::entrypoint(); -} - -#[cfg(test)] -mod tests { - use plonky2x::prelude::DefaultParameters; - use plonky2x::utils; - - use super::*; - - type L = DefaultParameters; - const D: usize = 2; - - #[test] - fn test_circuit() { - env_logger::try_init().unwrap_or_default(); - - let mut builder = CircuitBuilder::::new(); - MapReduceValidatorCircuit::define(&mut builder); - let circuit = builder.build(); - - let input = circuit.input(); - let (proof, output) = circuit.prove(&input); - circuit.verify(&proof, &input, &output); - - MapReduceValidatorCircuit::test_serialization::(); - } -} diff --git a/succinct.json b/succinct.json index 050903a15..c4bae538d 100644 --- a/succinct.json +++ b/succinct.json @@ -1,8 +1,15 @@ { "entrypoints": [ + { + "name": "evm", + "framework": "plonky2x", + "baseDir": ".", + "buildCommand": "mkdir build && cargo run --release --example evm build && mv ./target/release/examples/evm ./build/evm", + "proveCommand": "./build/evm prove input.json" + }, { "name": "eth_call", - "framework": "succinctx", + "framework": "rustx", "baseDir": ".", "buildCommand": "mkdir build && cargo run --release --example eth_call build && mv ./target/release/examples/eth_call ./build/eth_call", "proveCommand": "./build/eth_call prove input.json" From ea5cd21f1661923a1bcddad1a856fa54ad24e49e Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 9 Oct 2023 16:53:41 -0700 Subject: [PATCH 08/19] feat: assets --- plonky2x/core/src/backend/function/args.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plonky2x/core/src/backend/function/args.rs b/plonky2x/core/src/backend/function/args.rs index 77c1695b3..46c9aff3c 100644 --- a/plonky2x/core/src/backend/function/args.rs +++ b/plonky2x/core/src/backend/function/args.rs @@ -17,7 +17,7 @@ pub struct ProveArgs { #[arg(long, default_value = "./build")] pub build_dir: String, - #[arg(long)] + #[arg(long, default_value = "/verifier-build")] pub wrapper_path: String, } From e8b4d23a4af5b8be53aa58c66d4d9b3924fa010e Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 9 Oct 2023 17:54:54 -0700 Subject: [PATCH 09/19] fix: abi encode sequence --- rustx/examples/eth_call.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rustx/examples/eth_call.rs b/rustx/examples/eth_call.rs index fb42f9893..f853c796f 100644 --- a/rustx/examples/eth_call.rs +++ b/rustx/examples/eth_call.rs @@ -34,7 +34,7 @@ impl Program for EthCall { fn run(input_bytes: Vec) -> Vec { // Decode the input bytes into the request tuple. let (chain_id, block_number, from_address, to_address, calldata) = - EthCallRequestTuple::abi_decode(&input_bytes, true).unwrap(); + EthCallRequestTuple::abi_decode_sequence(&input_bytes, true).unwrap(); // Get relevant enviroment variables and initialize the HTTP provider. dotenv::dotenv().ok(); @@ -74,7 +74,7 @@ mod tests { #[cfg_attr(feature = "ci", ignore)] fn test_eth_call() { // Construct the request. - let request = EthCallRequestTuple::abi_encode(&( + let request = EthCallRequestTuple::abi_encode_sequence(&( 5u32, 9591261u64, address!("355348b048b5b491793110bb76d7a2723262d175"), @@ -86,7 +86,7 @@ mod tests { let input_hex = hex::encode(request.clone()); assert_eq!( input_hex, - "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000009259dd000000000000000000000000355348b048b5b491793110bb76d7a2723262d175000000000000000000000000d555cd8277b0e16860f0ae44fcbc2ed94dfce9da00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a4050ddcce00000000000000000000000003acd25623e5999fddc27be7fdb904358700f3ae000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000064eb9d30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000009259dd000000000000000000000000355348b048b5b491793110bb76d7a2723262d175000000000000000000000000d555cd8277b0e16860f0ae44fcbc2ed94dfce9da00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a4050ddcce00000000000000000000000003acd25623e5999fddc27be7fdb904358700f3ae000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000064eb9d30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ); // Compute the output. From 54c9f016a34f44eb049b942b62918c5b7c702984 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Tue, 10 Oct 2023 16:13:51 -0700 Subject: [PATCH 10/19] feat: cleanup --- contracts/src/FunctionGatewayV2.sol | 294 ++++++++++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 contracts/src/FunctionGatewayV2.sol diff --git a/contracts/src/FunctionGatewayV2.sol b/contracts/src/FunctionGatewayV2.sol new file mode 100644 index 000000000..9736c2ee1 --- /dev/null +++ b/contracts/src/FunctionGatewayV2.sol @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.16; + +import {IFunctionGateway, FunctionRequest} from "./interfaces/IFunctionGateway.sol"; +import {IFunctionVerifier} from "./interfaces/IFunctionVerifier.sol"; +import {FunctionRegistry} from "./FunctionRegistry.sol"; +import {TimelockedUpgradeable} from "./upgrades/TimelockedUpgradeable.sol"; + +contract FunctionGateway is + IFunctionGateway, + FunctionRegistry, + TimelockedUpgradeable +{ + /// @dev The default gas limit for requests. + uint256 public constant DEFAULT_GAS_LIMIT = 1000000; + + /// @dev A nonce for keeping track of requests. + uint32 public nonce; + + /// @dev A mapping from request nonces to request hashes. + mapping(uint32 => bytes32) public requests; + + /// @dev The current function identifier. + bytes32 public currentVerifiedFunctionId; + + /// @dev The current function input hash. + bytes32 public currentVerifiedInputHash; + + /// @dev The current function output. + bytes public currentVerifiedOutput; + + /// @dev Initializes the contract. + /// @param _timelock The address of the timelock contract. + /// @param _guardian The address of the guardian. + function initialize( + address _timelock, + address _guardian + ) external initializer { + __TimelockedUpgradeable_init(_timelock, _guardian); + } + + /// @dev Creates a onchain request for a proof. The output and proof is fulfilled asynchronously + /// by the provided callback. + /// @param _functionId The function identifier. + /// @param _input The function input. + /// @param _context The function context. + /// @param _callbackSelector The selector of the callback function. + function request( + bytes32 _functionId, + bytes memory _input, + bytes memory _context, + bytes4 _callbackSelector + ) external payable returns (bytes32) { + return + request( + _functionId, + _input, + _context, + _callbackSelector, + DEFAULT_GAS_LIMIT + ); + } + + /// @dev Creates a onchain request for a proof. The output and proof is fulfilled asynchronously + /// by the provided callback. + /// @param _functionId The function identifier. + /// @param _input The function input. + /// @param _context The function context. + /// @param _callbackSelector The selector of the callback function. + /// @param _callbackGasLimit The gas limit for the callback function. + function zkRequest( + bytes32 _functionId, + bytes memory _input, + bytes memory _context, + bytes4 _callbackSelector, + uint32 _callbackGasLimit + ) external payable returns (bytes32) { + // Compute the callback hash uniquely associated with this request. + bytes32 inputHash = sha256(_input); + bytes32 contextHash = sha256(_context); + address callbackAddress = msg.sender; + bytes32 requestHash = _requestHash( + nonce, + _functionId, + inputHash, + contextHash, + callbackAddress, + _callbackSelector, + _callbackGasLimit + ); + + // Store the callback hash. + requests[nonce] = requestHash; + emit Request( + nonce, + _functionId, + _input, + _context, + _callbackSelector, + _callbackGasLimit + ); + + // Increment the nonce. + nonce++; + return callbackHash; + } + + /// @dev Fulfills a request by providing the output and proof. + /// @param _nonce The nonce of the request. + /// @param _functionId The function identifier. + /// @param _inputHash The hash of the function input. + /// @param _callbackAddress The address of the callback contract. + /// @param _callbackSelector The selector of the callback function. + /// @param _callbackGasLimit The gas limit for the callback function. + /// @param _context The function context. + /// @param _output The function output. + /// @param _proof The function proof. + function zkRequestFulfill( + uint32 _nonce, + bytes32 _functionId, + bytes32 _inputHash, + address _callbackAddress, + bytes4 _callbackSelector, + uint32 _callbackGasLimit, + bytes memory _context, + bytes memory _output, + bytes memory _proof + ) external { + // Reconstruct the callback hash. + bytes32 contextHash = sha256(_context); + bytes32 requestHash = _requestHash( + _nonce, + _functionId, + _inputHash, + contextHash, + _callbackAddress, + _callbackSelector, + _callbackGasLimit + ); + + // Assert that the callback hash is unfilfilled. + if (requests[_nonce] != requestHash) { + revert InvalidFulfill(_nonce, requests[_nonce], requestHash); + } + + // Compute the output hash. + bytes32 outputHash = sha256(_output); + + // Verify the proof. + _verify(_functionId, _inputHash, outputHash, _proof); + + // Execute the callback. + (bool status, ) = _callbackAddress.call( + abi.encodeWithSelector(_callbackSelector, _output, _context) + ); + + // If the callback failed, revert. + require(status, "FunctionGateway: callback failed"); + + // Delete the callback hash for a gas refund. + delete requests[_nonce]; + } + + /// @dev If the call matches the currently verified function, returns the output. Otherwise, + /// this function reverts. + /// @param _functionId The function identifier. + /// @param _input The function input. + function zkCall( + bytes32 _functionId, + bytes memory _input + ) external returns (bytes memory) { + if ( + currentVerifiedFunctionId == _functionId && + currentVerifiedInputHash == sha256(_input) + ) { + return currentVerifiedCall.output; + } + revert("FunctionGateway: not verified"); + } + + /// @dev The entrypoint for fulfilling a call. + /// @param _functionId The function identifier. + /// @param _input The function input. + /// @param _output The function output. + /// @param _proof The function proof. + /// @param _callbackAddress The address of the callback contract. + /// @param _callbackData The data for the callback function. + function zkCallFulfill( + bytes32 _functionId, + bytes memory _input, + bytes memory _output, + bytes memory _proof, + address _callbackAddress, + bytes memory _callbackData + ) external { + // Compute the input and output hashes. + bytes32 inputHash = sha256(_input); + bytes32 outputHash = sha256(_output); + + // Verify the proof. + _verify(_functionId, inputHash, outputHash, _proof); + + // Set the current verified call. + currentVerifiedFunctionId = _functionId; + currentVerifiedInputHash = inputHash; + currentVerifiedOutput = _output; + + // Execute the callback. + (bool status, ) = _callbackAddress.call(_callbackData); + if (!status) { + revert("FunctionGateway: callback failed"); + } + + // Delete the current verified call. + delete currentVerifiedFunctionId; + delete currentVerifiedInputHash; + delete currentVerifiedOutput; + } + + /// @dev Computes a unique identifier for a request. + /// @param _functionId The function identifier. + /// @param _inputHash The hash of the function input. + /// @param _contextHash The hash of the function context. + /// @param _callbackAddress The address of the callback contract. + /// @param _callbackSelector The selector of the callback function. + /// @param _callbackGasLimit The gas limit for the callback function. + function _requestHash( + uint32 _nonce, + bytes32 _functionId, + bytes32 _inputHash, + bytes32 _contextHash, + address _callbackAddress, + bytes4 _callbackSelector, + uint32 _callbackGasLimit + ) internal returns (bytes32) { + return + keccak256( + abi.encodePacked( + _nonce, + _functionId, + _inputHash, + _contextHash, + _callbackAddress, + _callbackSelector, + _callbackGasLimit + ) + ); + } + + /// @dev Verifies a proof with respect to a function identifier, input hash, and output hash. + /// @param _functionId The function identifier. + /// @param _inputHash The hash of the function input. + /// @param _outputHash The hash of the function output. + /// @param _proof The function proof. + function _verify( + bytes32 _functionId, + bytes32 _inputHash, + bytes32 _outputHash, + bytes memory _proof + ) internal { + address verifier = verifiers[_functionId]; + if ( + !IFunctionVerifier(verifier).verify(_inputHash, _outputHash, _proof) + ) { + revert InvalidProof( + address(verifier), + r.inputHash, + _outputHash, + _proof + ); + } + } + + /// @dev This empty reserved space to add new variables without shifting down storage. + /// See: https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + uint256[50] private __gap; + + // TODO: fix + event Request( + uint32 nonce, + bytes32 functionId, + bytes input, + bytes context, + bytes4 callbackSelector, + uint256 callbackGasLimit + ); + + error InvalidCallback( + uint256 nonce, + bytes32 expectedCallbackHash, + bytes32 callbackHash + ); +} From 297f706be05fb3dce3195bd5f4e2a027e9d806bc Mon Sep 17 00:00:00 2001 From: John Guibas Date: Tue, 10 Oct 2023 16:15:43 -0700 Subject: [PATCH 11/19] feat: cleanup --- contracts/src/FunctionGatewayV2.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/src/FunctionGatewayV2.sol b/contracts/src/FunctionGatewayV2.sol index 9736c2ee1..72849024a 100644 --- a/contracts/src/FunctionGatewayV2.sol +++ b/contracts/src/FunctionGatewayV2.sol @@ -46,14 +46,14 @@ contract FunctionGateway is /// @param _input The function input. /// @param _context The function context. /// @param _callbackSelector The selector of the callback function. - function request( + function zkRequest( bytes32 _functionId, bytes memory _input, bytes memory _context, bytes4 _callbackSelector ) external payable returns (bytes32) { return - request( + zkRequest( _functionId, _input, _context, From 850a2d9f798a87dc282cae82b9064b6326263397 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Tue, 10 Oct 2023 17:06:00 -0700 Subject: [PATCH 12/19] feat: cleanup --- contracts/.solhint.json | 8 +- contracts/script/deploy/FunctionGateway.s.sol | 30 +- contracts/script/deploy/StorageOracle.s.sol | 37 -- contracts/script/deploy/StorageVerifier.sol | 27 - contracts/src/FunctionGateway.sol | 423 +++++++------ contracts/src/FunctionGatewayV2.sol | 294 --------- contracts/src/FunctionRegistry.sol | 47 +- contracts/src/examples/secp256r1/Example.sol | 26 - .../src/examples/secp256r1/Secp256r1.sol | 32 - .../src/examples/storage/NounsOwnership.sol | 41 -- .../src/examples/storage/StorageOracle.sol | 86 --- .../src/examples/storage/StorageVerifier.sol | 576 ------------------ contracts/src/interfaces/IFunctionGateway.sol | 126 ++-- contracts/src/mocks/MockFunctionGateway.sol | 140 ----- .../src/upgrades/TimelockedUpgradeable.sol | 18 +- contracts/test/FunctionGateway.t.sol | 288 --------- contracts/test/NounsOwnership.t.sol | 150 ----- contracts/test/TestUtils.sol | 98 --- contracts/test/fixtures/nouns-fixture.json | 4 - 19 files changed, 348 insertions(+), 2103 deletions(-) delete mode 100644 contracts/script/deploy/StorageOracle.s.sol delete mode 100644 contracts/script/deploy/StorageVerifier.sol delete mode 100644 contracts/src/FunctionGatewayV2.sol delete mode 100644 contracts/src/examples/secp256r1/Example.sol delete mode 100644 contracts/src/examples/secp256r1/Secp256r1.sol delete mode 100644 contracts/src/examples/storage/NounsOwnership.sol delete mode 100644 contracts/src/examples/storage/StorageOracle.sol delete mode 100644 contracts/src/examples/storage/StorageVerifier.sol delete mode 100644 contracts/src/mocks/MockFunctionGateway.sol delete mode 100644 contracts/test/FunctionGateway.t.sol delete mode 100644 contracts/test/NounsOwnership.t.sol delete mode 100644 contracts/test/TestUtils.sol delete mode 100644 contracts/test/fixtures/nouns-fixture.json diff --git a/contracts/.solhint.json b/contracts/.solhint.json index 66ef4e72a..727fc79f0 100644 --- a/contracts/.solhint.json +++ b/contracts/.solhint.json @@ -3,11 +3,13 @@ "rules": { "code-complexity": ["error", 18], "compiler-version": ["error", ">=0.8.0"], - "max-line-length": ["warn", 100], - "no-console": "warn", + "max-line-length": ["off", 100], + "no-console": "off", "var-name-mixedcase": "off", "func-name-mixedcase": "off", "avoid-low-level-calls": "off", - "no-inline-assembly": "off" + "no-inline-assembly": "off", + "no-global-import": "off", + "no-empty-blocks": "off" } } \ No newline at end of file diff --git a/contracts/script/deploy/FunctionGateway.s.sol b/contracts/script/deploy/FunctionGateway.s.sol index ea81fcf17..8751474da 100644 --- a/contracts/script/deploy/FunctionGateway.s.sol +++ b/contracts/script/deploy/FunctionGateway.s.sol @@ -2,18 +2,18 @@ pragma solidity ^0.8.16; import "forge-std/console.sol"; -import {BaseScript} from "script/misc/Base.s.sol"; -import {FunctionGateway} from "src/FunctionGateway.sol"; -import {Proxy} from "src/upgrades/Proxy.sol"; +import {BaseScript} from "../misc/Base.s.sol"; +import {FunctionGateway} from "../../src/FunctionGateway.sol"; +import {Proxy} from "../../src/upgrades/Proxy.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; contract DeployFunctionGateway is BaseScript { function run() external broadcaster { - console.log("Deploying FunctionGateway contract on chain %s", Strings.toString(block.chainid)); + console.log( + "Deploying FunctionGateway contract on chain %s", + Strings.toString(block.chainid) + ); - // Check inputs - uint256 SCALAR = envUint256("SCALAR"); - address SUCCINCT_FEE_VAULT = envAddress("SUCCINCT_FEE_VAULT", block.chainid); address TIMELOCK = envAddress("TIMELOCK", block.chainid); address GUARDIAN = envAddress("GUARDIAN", block.chainid); bytes32 CREATE2_SALT = envBytes32("CREATE2_SALT"); @@ -23,15 +23,23 @@ contract DeployFunctionGateway is BaseScript { FunctionGateway gatewayImpl = new FunctionGateway{salt: CREATE2_SALT}(); FunctionGateway gateway; if (!UPGRADE) { - gateway = FunctionGateway(address(new Proxy{salt: CREATE2_SALT}(address(gatewayImpl), ""))); - gateway.initialize(SCALAR, SUCCINCT_FEE_VAULT, TIMELOCK, GUARDIAN); + gateway = FunctionGateway( + address(new Proxy{salt: CREATE2_SALT}(address(gatewayImpl), "")) + ); + gateway.initialize(TIMELOCK, GUARDIAN); } else { - gateway = FunctionGateway(envAddress("FUNCTION_GATEWAY", block.chainid)); + gateway = FunctionGateway( + envAddress("FUNCTION_GATEWAY", block.chainid) + ); gateway.upgradeTo(address(gatewayImpl)); } // Write address writeEnvAddress(DEPLOYMENT_FILE, "FUNCTION_GATEWAY", address(gateway)); - writeEnvAddress(DEPLOYMENT_FILE, "FUNCTION_GATEWAY_IMPL", address(gatewayImpl)); + writeEnvAddress( + DEPLOYMENT_FILE, + "FUNCTION_GATEWAY_IMPL", + address(gatewayImpl) + ); } } diff --git a/contracts/script/deploy/StorageOracle.s.sol b/contracts/script/deploy/StorageOracle.s.sol deleted file mode 100644 index 7eac391ee..000000000 --- a/contracts/script/deploy/StorageOracle.s.sol +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -import "forge-std/console.sol"; -import {BaseScript} from "script/misc/Base.s.sol"; -import {StorageOracle} from "src/examples/storage/StorageOracle.sol"; -import {Proxy} from "src/upgrades/Proxy.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; - -contract DeployStorageOracle is BaseScript { - function run() external broadcaster { - console.log("Deploying StorageOracle contract on chain %s", Strings.toString(block.chainid)); - - // Check inputs - address FUNCTION_GATEWAY = envAddress("FUNCTION_GATEWAY", block.chainid); - bytes32 FUNCTION_ID = envBytes32("FUNCTION_ID"); - address TIMELOCK = envAddress("TIMELOCK", block.chainid); - address GUARDIAN = envAddress("GUARDIAN", block.chainid); - bytes32 CREATE2_SALT = envBytes32("CREATE2_SALT"); - bool UPGRADE = envBool("UPGRADE_VIA_EOA", false); - - // Deploy contract - StorageOracle gatewayImpl = new StorageOracle{salt: CREATE2_SALT}(); - StorageOracle gateway; - if (!UPGRADE) { - gateway = StorageOracle(address(new Proxy{salt: CREATE2_SALT}(address(gatewayImpl), ""))); - gateway.initialize(FUNCTION_GATEWAY, FUNCTION_ID, TIMELOCK, GUARDIAN); - } else { - gateway = StorageOracle(envAddress("STORAGE_ORACLE", block.chainid)); - gateway.upgradeTo(address(gatewayImpl)); - } - - // Write address - writeEnvAddress(DEPLOYMENT_FILE, "STORAGE_ORACLE", address(gateway)); - writeEnvAddress(DEPLOYMENT_FILE, "STORAGE_ORACLE_IMPL", address(gatewayImpl)); - } -} diff --git a/contracts/script/deploy/StorageVerifier.sol b/contracts/script/deploy/StorageVerifier.sol deleted file mode 100644 index d08bd066a..000000000 --- a/contracts/script/deploy/StorageVerifier.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -import "forge-std/console.sol"; -import {BaseScript} from "script/misc/Base.s.sol"; -import {StorageVerifier} from "src/examples/storage/StorageVerifier.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; -import {IFunctionRegistry} from "src/interfaces/IFunctionRegistry.sol"; - -contract DeployStorageVerifier is BaseScript { - function run() external broadcaster { - console.log("Deploying StorageVerifier contract on chain %s", Strings.toString(block.chainid)); - - // Check inputs - address FUNCTION_GATEWAY = envAddress("FUNCTION_GATEWAY", block.chainid); - bytes32 CREATE2_SALT = envBytes32("CREATE2_SALT"); - - // Deploy contract - StorageVerifier verifier = new StorageVerifier{salt: CREATE2_SALT}(); - bytes32 functionId = IFunctionRegistry(FUNCTION_GATEWAY).registerFunction(address(verifier), "storage"); - console.log("FunctionId:"); - console.logBytes32(functionId); - - // Write address - writeEnvAddress(DEPLOYMENT_FILE, "STORAGE_VERIFIER", address(verifier)); - } -} diff --git a/contracts/src/FunctionGateway.sol b/contracts/src/FunctionGateway.sol index cb8163980..d0b98c16f 100644 --- a/contracts/src/FunctionGateway.sol +++ b/contracts/src/FunctionGateway.sol @@ -2,246 +2,281 @@ pragma solidity ^0.8.16; -import {IFunctionGateway, FunctionRequest} from "./interfaces/IFunctionGateway.sol"; +import {IFunctionGateway} from "./interfaces/IFunctionGateway.sol"; import {IFunctionVerifier} from "./interfaces/IFunctionVerifier.sol"; import {FunctionRegistry} from "./FunctionRegistry.sol"; import {TimelockedUpgradeable} from "./upgrades/TimelockedUpgradeable.sol"; -import {IFeeVault} from "src/payments/interfaces/IFeeVault.sol"; - -contract FunctionGateway is IFunctionGateway, FunctionRegistry, TimelockedUpgradeable { - /// @dev The proof id for an aggregate proof. - bytes32 public constant AGGREGATION_FUNCTION_ID = keccak256("AGGREGATION_FUNCTION_ID"); +contract FunctionGateway is + IFunctionGateway, + FunctionRegistry, + TimelockedUpgradeable +{ /// @dev The default gas limit for requests. - uint256 public constant DEFAULT_GAS_LIMIT = 1000000; + uint32 public constant DEFAULT_GAS_LIMIT = 1000000; + + /// @dev A nonce for keeping track of requests. + uint32 public nonce; - /// @dev Keeps track of the nonce for generating request ids. - uint256 public nonce; + /// @dev A mapping from request nonces to request hashes. + mapping(uint32 => bytes32) public requests; - /// @dev Maps request ids to their corresponding requests. - mapping(bytes32 => FunctionRequest) public requests; + /// @dev The currently verified function identifier. + bytes32 public verifiedFunctionId; - /// @notice The dynamic scalar for requests. - uint256 public scalar; + /// @dev The currently verified function input hash. + bytes32 public verifiedInputHash; - /// @notice A reference to the contract where fees are sent. - /// @dev During the request functions, this is used to add msg.value to the sender's balance. - address public feeVault; + /// @dev The currently verified function output. + bytes public verifiedOutput; - function initialize(uint256 _scalar, address _feeVault, address _timelock, address _guardian) - external - initializer - { - scalar = _scalar; - feeVault = _feeVault; + /// @dev Initializes the contract. + /// @param _timelock The address of the timelock contract. + /// @param _guardian The address of the guardian. + function initialize( + address _timelock, + address _guardian + ) external initializer { __TimelockedUpgradeable_init(_timelock, _guardian); } - function request(bytes32 _functionId, bytes memory _input, bytes4 _callbackSelector, bytes memory _context) - external - payable - returns (bytes32) - { - return request(_functionId, _input, _callbackSelector, _context, DEFAULT_GAS_LIMIT, tx.origin); + /// @dev Creates a onchain request for a proof. The output and proof is fulfilled asynchronously + /// by the provided callback. + /// @param _functionId The function identifier. + /// @param _input The function input. + /// @param _context The function context. + /// @param _callbackSelector The selector of the callback function. + function zkRequest( + bytes32 _functionId, + bytes memory _input, + bytes memory _context, + bytes4 _callbackSelector + ) external returns (bytes32) { + return + zkRequest( + _functionId, + _input, + _context, + _callbackSelector, + DEFAULT_GAS_LIMIT + ); } - /// @dev Requests for a proof to be generated by the marketplace. - /// @param _functionId The id of the proof to be generated. - /// @param _input The input to the proof. - /// @param _context The context of the runtime. + /// @dev Creates a onchain request for a proof. The output and proof is fulfilled asynchronously + /// by the provided callback. + /// @param _functionId The function identifier. + /// @param _input The function input. + /// @param _context The function context. /// @param _callbackSelector The selector of the callback function. - function request( + /// @param _callbackGasLimit The gas limit for the callback function. + function zkRequest( bytes32 _functionId, bytes memory _input, - bytes4 _callbackSelector, bytes memory _context, - uint256 _gasLimit, - address _refundAccount - ) public payable returns (bytes32) { + bytes4 _callbackSelector, + uint32 _callbackGasLimit + ) public returns (bytes32) { + // Compute the callback hash uniquely associated with this request. bytes32 inputHash = sha256(_input); - bytes32 contextHash = keccak256(_context); - FunctionRequest memory r = FunctionRequest({ - functionId: _functionId, - inputHash: inputHash, - outputHash: bytes32(0), - contextHash: contextHash, - callbackAddress: msg.sender, - callbackSelector: _callbackSelector, - proofFulfilled: false, - callbackFulfilled: false - }); - - uint256 feeAmount = _handlePayment(_gasLimit, _refundAccount, msg.sender, msg.value); - - bytes32 requestId = keccak256(abi.encode(nonce, r)); - requests[requestId] = r; - - emit ProofRequested(nonce, _functionId, requestId, _input, _context, _gasLimit, feeAmount); + bytes32 contextHash = sha256(_context); + address callbackAddress = msg.sender; + bytes32 requestHash = _requestHash( + nonce, + _functionId, + inputHash, + contextHash, + callbackAddress, + _callbackSelector, + _callbackGasLimit + ); + + // Store the callback hash. + requests[nonce] = requestHash; + emit Request( + nonce, + _functionId, + _input, + _context, + _callbackSelector, + _callbackGasLimit + ); + + // Increment the nonce. nonce++; - return requestId; + return requestHash; } - /// @dev The entrypoint for fulfilling proofs which are not in batches. - /// @param _requestId The id of the request to be fulfilled. - /// @param _outputHash The output hash of the proof. - /// @param _proof The proof. - function fulfill(bytes32 _requestId, bytes32 _outputHash, bytes memory _proof) external { - // Do some sanity checks. - FunctionRequest storage r = requests[_requestId]; - if (r.callbackAddress == address(0)) { - revert RequestNotFound(_requestId); - } else if (r.proofFulfilled) { - revert ProofAlreadyFulfilled(_requestId); + /// @dev Fulfills a request by providing the output and proof. + /// @param _nonce The nonce of the request. + /// @param _functionId The function identifier. + /// @param _inputHash The hash of the function input. + /// @param _callbackAddress The address of the callback contract. + /// @param _callbackSelector The selector of the callback function. + /// @param _callbackGasLimit The gas limit for the callback function. + /// @param _context The function context. + /// @param _output The function output. + /// @param _proof The function proof. + function zkRequestFulfill( + uint32 _nonce, + bytes32 _functionId, + bytes32 _inputHash, + address _callbackAddress, + bytes4 _callbackSelector, + uint32 _callbackGasLimit, + bytes memory _context, + bytes memory _output, + bytes memory _proof + ) external { + // Reconstruct the callback hash. + bytes32 contextHash = sha256(_context); + bytes32 requestHash = _requestHash( + _nonce, + _functionId, + _inputHash, + contextHash, + _callbackAddress, + _callbackSelector, + _callbackGasLimit + ); + + // Assert that the callback hash is unfilfilled. + if (requests[_nonce] != requestHash) { + revert InvalidRequest(_nonce, requests[_nonce], requestHash); } - // Update the request. - r.proofFulfilled = true; - r.outputHash = _outputHash; + // Compute the output hash. + bytes32 outputHash = sha256(_output); // Verify the proof. - address verifier = verifiers[r.functionId]; - if (!IFunctionVerifier(verifier).verify(r.inputHash, _outputHash, _proof)) { - revert InvalidProof(address(verifier), r.inputHash, _outputHash, _proof); - } + _verify(_functionId, _inputHash, outputHash, _proof); - emit ProofFulfilled(_requestId, _outputHash, _proof); - } + // Execute the callback. + (bool status, ) = _callbackAddress.call( + abi.encodeWithSelector(_callbackSelector, _output, _context) + ); - /// @dev The entrypoint for fulfilling proofs which are in batches. - /// @param _requestIds The ids of the requests to be fulfilled. - /// @param _aggregateProof The aggregate proof. - /// @param _inputsRoot The root of the inputs. - /// @param _outputHashes The output hashes of the proofs. - /// @param _outputsRoot The root of the outputs. - /// @param _verificationKeyRoot The root of the verification keys. - function fulfillBatch( - bytes32[] memory _requestIds, - bytes memory _aggregateProof, - bytes32 _inputsRoot, - bytes32[] memory _outputHashes, - bytes32 _outputsRoot, - bytes32 _verificationKeyRoot - ) external { - // Collect the input hashes and verification key hashes. - bytes32[] memory inputHashes = new bytes32[](_requestIds.length); - bytes32[] memory verificationKeyHashes = new bytes32[](_requestIds.length); - for (uint256 i = 0; i < _requestIds.length; i++) { - bytes32 requestId = _requestIds[i]; - FunctionRequest storage r = requests[requestId]; - if (r.callbackAddress == address(0)) { - revert RequestNotFound(requestId); - } else if (r.proofFulfilled) { - revert ProofAlreadyFulfilled(requestId); - } - inputHashes[i] = r.inputHash; - address verifier = verifiers[r.functionId]; - verificationKeyHashes[i] = IFunctionVerifier(verifier).verificationKeyHash(); + // If the callback failed, revert. + if (!status) { + revert CallbackFailed(_callbackSelector, _output, _context); } - // Do some sanity checks. - if (_requestIds.length != _outputHashes.length) { - revert LengthMismatch(_requestIds.length, _outputHashes.length); - } else if (_inputsRoot != keccak256(abi.encode(inputHashes))) { - revert InputsRootMismatch(_inputsRoot, inputHashes); - } else if (_outputsRoot != keccak256(abi.encode(_outputHashes))) { - revert OutputsRootMismatch(_outputsRoot, _outputHashes); - } else if (_verificationKeyRoot != keccak256(abi.encode(verificationKeyHashes))) { - revert VerificationKeysRootMismatch(_verificationKeyRoot, verificationKeyHashes); - } + // Delete the callback hash for a gas refund. + delete requests[_nonce]; - // Update the requests. - for (uint256 i = 0; i < _requestIds.length; i++) { - bytes32 requestId = _requestIds[i]; - requests[requestId].proofFulfilled = true; - requests[requestId].outputHash = _outputHashes[i]; - } + // Emit event. + emit RequestFulfilled(_nonce, _functionId, _inputHash, outputHash); + } - // Verify the aggregate proof. - address aggregationVerifier = verifiers[AGGREGATION_FUNCTION_ID]; - if (!IFunctionVerifier(aggregationVerifier).verify(_inputsRoot, _outputsRoot, _aggregateProof)) { - revert InvalidProof(address(aggregationVerifier), _inputsRoot, _outputsRoot, _aggregateProof); + /// @dev If the call matches the currently verified function, returns the output. Otherwise, + /// this function reverts. + /// @param _functionId The function identifier. + /// @param _input The function input. + function zkCall( + bytes32 _functionId, + bytes memory _input + ) external view returns (bytes memory) { + bytes32 inputHash = sha256(_input); + if ( + verifiedFunctionId == _functionId && verifiedInputHash == inputHash + ) { + return verifiedOutput; } - - emit ProofBatchFulfilled( - _requestIds, _aggregateProof, _inputsRoot, _outputHashes, _outputsRoot, _verificationKeyRoot - ); + revert InvalidCall(_functionId, inputHash); } - /// @dev Fulfills the callback for a request. - /// @param _requestId The id of the request to be fulfilled. - /// @param _output The output of the proof. - /// @param _context The context of the runtime. - function callback(bytes32 _requestId, bytes memory _output, bytes memory _context) external { - // Do some sanity checks. - FunctionRequest storage r = requests[_requestId]; - if (r.callbackFulfilled) { - revert CallbackAlreadyFulfilled(_requestId); - } else if (r.callbackAddress == address(0)) { - revert RequestNotFound(_requestId); - } else if (r.contextHash != keccak256(_context)) { - revert ContextMismatch(_requestId, _context); - } else if (r.outputHash != sha256(_output)) { - revert OutputMismatch(_requestId, _output); - } else if (!r.proofFulfilled) { - revert ProofNotFulfilled(_requestId); - } + /// @dev The entrypoint for fulfilling a call. + /// @param _functionId The function identifier. + /// @param _input The function input. + /// @param _output The function output. + /// @param _proof The function proof. + /// @param _callbackAddress The address of the callback contract. + /// @param _callbackData The data for the callback function. + function zkCallFulfill( + bytes32 _functionId, + bytes memory _input, + bytes memory _output, + bytes memory _proof, + address _callbackAddress, + bytes memory _callbackData + ) external { + // Compute the input and output hashes. + bytes32 inputHash = sha256(_input); + bytes32 outputHash = sha256(_output); - // Update the request. - r.callbackFulfilled = true; + // Verify the proof. + _verify(_functionId, inputHash, outputHash, _proof); + + // Set the current verified call. + verifiedFunctionId = _functionId; + verifiedInputHash = inputHash; + verifiedOutput = _output; - // Call the callback. - (bool status,) = r.callbackAddress.call(abi.encodeWithSelector(r.callbackSelector, _output, _context)); + // Execute the callback. + (bool status, ) = _callbackAddress.call(_callbackData); if (!status) { - revert CallbackFailed(r.callbackAddress, r.callbackSelector); + revert CallFailed(_callbackAddress, _callbackData); } - emit CallbackFulfilled(_requestId, _output, _context); - } + // Delete the current verified call. + delete verifiedFunctionId; + delete verifiedInputHash; + delete verifiedOutput; - /// @notice Update the scalar. - function updateScalar(uint256 _scalar) external onlyGuardian { - scalar = _scalar; - - emit ScalarUpdated(_scalar); - } - - /// @notice Calculates the feeAmount for the default gasLimit. - function calculateFeeAmount() external view returns (uint256 feeAmount) { - return calculateFeeAmount(DEFAULT_GAS_LIMIT); + // Emit event. + emit Call(_functionId, inputHash, outputHash); } - /// @notice Calculates the feeAmount for a given gasLimit. - function calculateFeeAmount(uint256 _gasLimit) public view returns (uint256 feeAmount) { - if (scalar == 0) { - feeAmount = tx.gasprice * _gasLimit; - } else { - feeAmount = tx.gasprice * _gasLimit * scalar; - } + /// @dev Computes a unique identifier for a request. + /// @param _functionId The function identifier. + /// @param _inputHash The hash of the function input. + /// @param _contextHash The hash of the function context. + /// @param _callbackAddress The address of the callback contract. + /// @param _callbackSelector The selector of the callback function. + /// @param _callbackGasLimit The gas limit for the callback function. + function _requestHash( + uint32 _nonce, + bytes32 _functionId, + bytes32 _inputHash, + bytes32 _contextHash, + address _callbackAddress, + bytes4 _callbackSelector, + uint32 _callbackGasLimit + ) internal pure returns (bytes32) { + return + keccak256( + abi.encodePacked( + _nonce, + _functionId, + _inputHash, + _contextHash, + _callbackAddress, + _callbackSelector, + _callbackGasLimit + ) + ); } - /// @dev Calculates the feeAmount for the request, sends the feeAmount to the FeeVault, and - /// sends the excess amount as a refund to the refundAccount. - function _handlePayment(uint256 _gasLimit, address _refundAccount, address _senderAccount, uint256 _value) - private - returns (uint256 feeAmount) - { - feeAmount = calculateFeeAmount(_gasLimit); - if (_value < feeAmount) { - revert InsufficientFeeAmount(feeAmount, _value); - } - - // Send the feeAmount amount to the fee vault. - if (feeAmount > 0 && feeVault != address(0)) { - IFeeVault(feeVault).depositNative{value: feeAmount}(_senderAccount); - } - - // Send the excess amount to the refund account. - uint256 refundAmount = _value - feeAmount; - if (refundAmount > 0) { - (bool success,) = _refundAccount.call{value: refundAmount}(""); - if (!success) { - revert RefundFailed(_refundAccount, refundAmount); - } + /// @dev Verifies a proof with respect to a function identifier, input hash, and output hash. + /// @param _functionId The function identifier. + /// @param _inputHash The hash of the function input. + /// @param _outputHash The hash of the function output. + /// @param _proof The function proof. + function _verify( + bytes32 _functionId, + bytes32 _inputHash, + bytes32 _outputHash, + bytes memory _proof + ) internal { + address verifier = verifiers[_functionId]; + if ( + !IFunctionVerifier(verifier).verify(_inputHash, _outputHash, _proof) + ) { + revert InvalidProof( + address(verifier), + _inputHash, + _outputHash, + _proof + ); } } diff --git a/contracts/src/FunctionGatewayV2.sol b/contracts/src/FunctionGatewayV2.sol deleted file mode 100644 index 72849024a..000000000 --- a/contracts/src/FunctionGatewayV2.sol +++ /dev/null @@ -1,294 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.16; - -import {IFunctionGateway, FunctionRequest} from "./interfaces/IFunctionGateway.sol"; -import {IFunctionVerifier} from "./interfaces/IFunctionVerifier.sol"; -import {FunctionRegistry} from "./FunctionRegistry.sol"; -import {TimelockedUpgradeable} from "./upgrades/TimelockedUpgradeable.sol"; - -contract FunctionGateway is - IFunctionGateway, - FunctionRegistry, - TimelockedUpgradeable -{ - /// @dev The default gas limit for requests. - uint256 public constant DEFAULT_GAS_LIMIT = 1000000; - - /// @dev A nonce for keeping track of requests. - uint32 public nonce; - - /// @dev A mapping from request nonces to request hashes. - mapping(uint32 => bytes32) public requests; - - /// @dev The current function identifier. - bytes32 public currentVerifiedFunctionId; - - /// @dev The current function input hash. - bytes32 public currentVerifiedInputHash; - - /// @dev The current function output. - bytes public currentVerifiedOutput; - - /// @dev Initializes the contract. - /// @param _timelock The address of the timelock contract. - /// @param _guardian The address of the guardian. - function initialize( - address _timelock, - address _guardian - ) external initializer { - __TimelockedUpgradeable_init(_timelock, _guardian); - } - - /// @dev Creates a onchain request for a proof. The output and proof is fulfilled asynchronously - /// by the provided callback. - /// @param _functionId The function identifier. - /// @param _input The function input. - /// @param _context The function context. - /// @param _callbackSelector The selector of the callback function. - function zkRequest( - bytes32 _functionId, - bytes memory _input, - bytes memory _context, - bytes4 _callbackSelector - ) external payable returns (bytes32) { - return - zkRequest( - _functionId, - _input, - _context, - _callbackSelector, - DEFAULT_GAS_LIMIT - ); - } - - /// @dev Creates a onchain request for a proof. The output and proof is fulfilled asynchronously - /// by the provided callback. - /// @param _functionId The function identifier. - /// @param _input The function input. - /// @param _context The function context. - /// @param _callbackSelector The selector of the callback function. - /// @param _callbackGasLimit The gas limit for the callback function. - function zkRequest( - bytes32 _functionId, - bytes memory _input, - bytes memory _context, - bytes4 _callbackSelector, - uint32 _callbackGasLimit - ) external payable returns (bytes32) { - // Compute the callback hash uniquely associated with this request. - bytes32 inputHash = sha256(_input); - bytes32 contextHash = sha256(_context); - address callbackAddress = msg.sender; - bytes32 requestHash = _requestHash( - nonce, - _functionId, - inputHash, - contextHash, - callbackAddress, - _callbackSelector, - _callbackGasLimit - ); - - // Store the callback hash. - requests[nonce] = requestHash; - emit Request( - nonce, - _functionId, - _input, - _context, - _callbackSelector, - _callbackGasLimit - ); - - // Increment the nonce. - nonce++; - return callbackHash; - } - - /// @dev Fulfills a request by providing the output and proof. - /// @param _nonce The nonce of the request. - /// @param _functionId The function identifier. - /// @param _inputHash The hash of the function input. - /// @param _callbackAddress The address of the callback contract. - /// @param _callbackSelector The selector of the callback function. - /// @param _callbackGasLimit The gas limit for the callback function. - /// @param _context The function context. - /// @param _output The function output. - /// @param _proof The function proof. - function zkRequestFulfill( - uint32 _nonce, - bytes32 _functionId, - bytes32 _inputHash, - address _callbackAddress, - bytes4 _callbackSelector, - uint32 _callbackGasLimit, - bytes memory _context, - bytes memory _output, - bytes memory _proof - ) external { - // Reconstruct the callback hash. - bytes32 contextHash = sha256(_context); - bytes32 requestHash = _requestHash( - _nonce, - _functionId, - _inputHash, - contextHash, - _callbackAddress, - _callbackSelector, - _callbackGasLimit - ); - - // Assert that the callback hash is unfilfilled. - if (requests[_nonce] != requestHash) { - revert InvalidFulfill(_nonce, requests[_nonce], requestHash); - } - - // Compute the output hash. - bytes32 outputHash = sha256(_output); - - // Verify the proof. - _verify(_functionId, _inputHash, outputHash, _proof); - - // Execute the callback. - (bool status, ) = _callbackAddress.call( - abi.encodeWithSelector(_callbackSelector, _output, _context) - ); - - // If the callback failed, revert. - require(status, "FunctionGateway: callback failed"); - - // Delete the callback hash for a gas refund. - delete requests[_nonce]; - } - - /// @dev If the call matches the currently verified function, returns the output. Otherwise, - /// this function reverts. - /// @param _functionId The function identifier. - /// @param _input The function input. - function zkCall( - bytes32 _functionId, - bytes memory _input - ) external returns (bytes memory) { - if ( - currentVerifiedFunctionId == _functionId && - currentVerifiedInputHash == sha256(_input) - ) { - return currentVerifiedCall.output; - } - revert("FunctionGateway: not verified"); - } - - /// @dev The entrypoint for fulfilling a call. - /// @param _functionId The function identifier. - /// @param _input The function input. - /// @param _output The function output. - /// @param _proof The function proof. - /// @param _callbackAddress The address of the callback contract. - /// @param _callbackData The data for the callback function. - function zkCallFulfill( - bytes32 _functionId, - bytes memory _input, - bytes memory _output, - bytes memory _proof, - address _callbackAddress, - bytes memory _callbackData - ) external { - // Compute the input and output hashes. - bytes32 inputHash = sha256(_input); - bytes32 outputHash = sha256(_output); - - // Verify the proof. - _verify(_functionId, inputHash, outputHash, _proof); - - // Set the current verified call. - currentVerifiedFunctionId = _functionId; - currentVerifiedInputHash = inputHash; - currentVerifiedOutput = _output; - - // Execute the callback. - (bool status, ) = _callbackAddress.call(_callbackData); - if (!status) { - revert("FunctionGateway: callback failed"); - } - - // Delete the current verified call. - delete currentVerifiedFunctionId; - delete currentVerifiedInputHash; - delete currentVerifiedOutput; - } - - /// @dev Computes a unique identifier for a request. - /// @param _functionId The function identifier. - /// @param _inputHash The hash of the function input. - /// @param _contextHash The hash of the function context. - /// @param _callbackAddress The address of the callback contract. - /// @param _callbackSelector The selector of the callback function. - /// @param _callbackGasLimit The gas limit for the callback function. - function _requestHash( - uint32 _nonce, - bytes32 _functionId, - bytes32 _inputHash, - bytes32 _contextHash, - address _callbackAddress, - bytes4 _callbackSelector, - uint32 _callbackGasLimit - ) internal returns (bytes32) { - return - keccak256( - abi.encodePacked( - _nonce, - _functionId, - _inputHash, - _contextHash, - _callbackAddress, - _callbackSelector, - _callbackGasLimit - ) - ); - } - - /// @dev Verifies a proof with respect to a function identifier, input hash, and output hash. - /// @param _functionId The function identifier. - /// @param _inputHash The hash of the function input. - /// @param _outputHash The hash of the function output. - /// @param _proof The function proof. - function _verify( - bytes32 _functionId, - bytes32 _inputHash, - bytes32 _outputHash, - bytes memory _proof - ) internal { - address verifier = verifiers[_functionId]; - if ( - !IFunctionVerifier(verifier).verify(_inputHash, _outputHash, _proof) - ) { - revert InvalidProof( - address(verifier), - r.inputHash, - _outputHash, - _proof - ); - } - } - - /// @dev This empty reserved space to add new variables without shifting down storage. - /// See: https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - uint256[50] private __gap; - - // TODO: fix - event Request( - uint32 nonce, - bytes32 functionId, - bytes input, - bytes context, - bytes4 callbackSelector, - uint256 callbackGasLimit - ); - - error InvalidCallback( - uint256 nonce, - bytes32 expectedCallbackHash, - bytes32 callbackHash - ); -} diff --git a/contracts/src/FunctionRegistry.sol b/contracts/src/FunctionRegistry.sol index 17d0221b9..73c5276f1 100644 --- a/contracts/src/FunctionRegistry.sol +++ b/contracts/src/FunctionRegistry.sol @@ -4,16 +4,19 @@ pragma solidity ^0.8.16; import {IFunctionRegistry} from "./interfaces/IFunctionRegistry.sol"; contract FunctionRegistry is IFunctionRegistry { - /// @dev Maps functionId's to their corresponding verifiers. + /// @dev Maps function identifiers to their corresponding verifiers. mapping(bytes32 => address) public verifiers; - /// @dev Maps functionId's to their corresponding owners. + /// @dev Maps function identifiers to their corresponding owners. mapping(bytes32 => address) public verifierOwners; /// @notice Registers a function, using a pre-deployed verifier. /// @param _verifier The address of the verifier. /// @param _name The name of the function to be registered. - function registerFunction(address _verifier, string memory _name) external returns (bytes32 functionId) { + function registerFunction( + address _verifier, + string memory _name + ) external returns (bytes32 functionId) { functionId = getFunctionId(msg.sender, _name); if (address(verifiers[functionId]) != address(0)) { revert FunctionAlreadyRegistered(functionId); // should call update instead @@ -30,10 +33,10 @@ contract FunctionRegistry is IFunctionRegistry { /// @notice Registers a function, using CREATE2 to deploy the verifier. /// @param _bytecode The bytecode of the verifier. /// @param _name The name of the function to be registered. - function deployAndRegisterFunction(bytes memory _bytecode, string memory _name) - external - returns (bytes32 functionId, address verifier) - { + function deployAndRegisterFunction( + bytes memory _bytecode, + string memory _name + ) external returns (bytes32 functionId, address verifier) { functionId = getFunctionId(msg.sender, _name); if (address(verifiers[functionId]) != address(0)) { revert FunctionAlreadyRegistered(functionId); // should call update instead @@ -49,7 +52,10 @@ contract FunctionRegistry is IFunctionRegistry { /// @notice Updates the function, using a pre-deployed verifier. /// @param _verifier The address of the verifier. /// @param _name The name of the function to be updated. - function updateFunction(address _verifier, string memory _name) external returns (bytes32 functionId) { + function updateFunction( + address _verifier, + string memory _name + ) external returns (bytes32 functionId) { functionId = getFunctionId(msg.sender, _name); if (msg.sender != verifierOwners[functionId]) { revert NotFunctionOwner(msg.sender, verifierOwners[functionId]); @@ -65,10 +71,10 @@ contract FunctionRegistry is IFunctionRegistry { /// @notice Updates the function, using CREATE2 to deploy the new verifier. /// @param _bytecode The bytecode of the verifier. /// @param _name The name of the function to be updated. - function deployAndUpdateFunction(bytes memory _bytecode, string memory _name) - external - returns (bytes32 functionId, address verifier) - { + function deployAndUpdateFunction( + bytes memory _bytecode, + string memory _name + ) external returns (bytes32 functionId, address verifier) { functionId = getFunctionId(msg.sender, _name); if (msg.sender != verifierOwners[functionId]) { revert NotFunctionOwner(msg.sender, verifierOwners[functionId]); @@ -82,15 +88,26 @@ contract FunctionRegistry is IFunctionRegistry { /// @notice Returns the functionId for a given owner and function name. /// @param _owner The owner of the function (sender of registerFunction). /// @param _name The name of the function. - function getFunctionId(address _owner, string memory _name) public pure returns (bytes32 functionId) { + function getFunctionId( + address _owner, + string memory _name + ) public pure returns (bytes32 functionId) { functionId = keccak256(abi.encode(_owner, _name)); } - function _deploy(bytes memory _bytecode, bytes32 _salt) internal returns (address deployedAddr) { + function _deploy( + bytes memory _bytecode, + bytes32 _salt + ) internal returns (address deployedAddr) { if (_bytecode.length == 0) revert EmptyBytecode(); assembly { - deployedAddr := create2(0, add(_bytecode, 32), mload(_bytecode), _salt) + deployedAddr := create2( + 0, + add(_bytecode, 32), + mload(_bytecode), + _salt + ) } if (deployedAddr == address(0)) revert FailedDeploy(); diff --git a/contracts/src/examples/secp256r1/Example.sol b/contracts/src/examples/secp256r1/Example.sol deleted file mode 100644 index 6467e19a7..000000000 --- a/contracts/src/examples/secp256r1/Example.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.16; - -import {Secp256r1} from "./Secp256r1.sol"; - -contract Example { - function a() external { - address gateway = address(0); - bytes32 functionId = bytes32(0); - uint256 r = 0; - uint256 s = 0; - bytes4 callbackSelector = Example.b.selector; - bytes memory context = abi.encode(r, s); - Secp256r1.request(gateway, functionId, r, s, callbackSelector, context); - } - - function b(bytes memory _output, bytes memory _context) external pure returns (uint256) { - bool verified = Secp256r1.decode(_output); - (uint256 r, uint256 s) = abi.decode(_context, (uint256, uint256)); - if (verified) { - return r + s; - } - return 0; - } -} diff --git a/contracts/src/examples/secp256r1/Secp256r1.sol b/contracts/src/examples/secp256r1/Secp256r1.sol deleted file mode 100644 index fd095c1fe..000000000 --- a/contracts/src/examples/secp256r1/Secp256r1.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.16; - -import {IFunctionGateway} from "../../interfaces/IFunctionGateway.sol"; - -library Secp256r1 { - /// @dev Requests for a Secp256r1 signature to be verified. - /// @param _gateway The gateway to the function. - /// @param _functionId The id of the function. - /// @param _r The r value of the signature. - /// @param _s The s value of the signature. - /// @param _callbackSelector The selector of the callback function. - /// @param _context The context of the runtime. - function request( - address _gateway, - bytes32 _functionId, - uint256 _r, - uint256 _s, - bytes4 _callbackSelector, - bytes memory _context - ) internal returns (bytes32) { - bytes memory input = abi.encode(_r, _s); - return IFunctionGateway(_gateway).request(_functionId, input, _callbackSelector, _context); - } - - /// @dev Decodes the output of the function. - /// @param _output The output of the function. - function decode(bytes memory _output) internal pure returns (bool) { - return abi.decode(_output, (bool)); - } -} diff --git a/contracts/src/examples/storage/NounsOwnership.sol b/contracts/src/examples/storage/NounsOwnership.sol deleted file mode 100644 index ac22511bd..000000000 --- a/contracts/src/examples/storage/NounsOwnership.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -import {StorageOracle} from "./StorageOracle.sol"; - -/// @notice Projects Nouns ownership from L1. -contract NounsOwnership { - /// @dev L1 Nouns NFT contract: https://etherscan.io/address/0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03 - address internal constant NOUNS_ADDRESS = 0x9C8fF314C9Bc7F6e59A9d9225Fb22946427eDC03; - - /// @dev Storage Slot in the contract for `mapping(uint256 => address) private _owners;` - uint256 internal constant OWNERS_SLOT = 3; - - address public immutable STORAGE_ORACLE; - - constructor(address _storageOracle) { - STORAGE_ORACLE = _storageOracle; - } - - /// @notice Requests that the ownership of a given noun be accouted for in voting. - /// @dev This can be called for an existing noun to update the owner. - /// @param _tokenId The token Id of the noun to claim. For example, to claim noun #100, this should be - /// 100. - function claimOwnership(uint256 _tokenId) external returns (bytes32 requestId) { - uint256 slot = uint256(keccak256(abi.encode(_tokenId, OWNERS_SLOT))); - requestId = StorageOracle(STORAGE_ORACLE).requestStorageSlot(NOUNS_ADDRESS, slot); - } - - /// @param _tokenId The token Id of the noun to check ownership of. - function ownerOf(uint256 _tokenId) external view returns (address owner) { - (bytes32 value,) = - StorageOracle(STORAGE_ORACLE).slots(NOUNS_ADDRESS, uint256(keccak256(abi.encode(_tokenId, OWNERS_SLOT)))); - return address(uint160(uint256(value))); - } - - /// @param _tokenId The token Id of the noun to last updated block of. - function lastUpdatedBlock(uint256 _tokenId) external view returns (uint256 blockNumber) { - (, blockNumber) = - StorageOracle(STORAGE_ORACLE).slots(NOUNS_ADDRESS, uint256(keccak256(abi.encode(_tokenId, OWNERS_SLOT)))); - } -} diff --git a/contracts/src/examples/storage/StorageOracle.sol b/contracts/src/examples/storage/StorageOracle.sol deleted file mode 100644 index 4855e12ff..000000000 --- a/contracts/src/examples/storage/StorageOracle.sol +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -import {IFunctionGateway} from "../../interfaces/IFunctionGateway.sol"; -import {TimelockedUpgradeable} from "../../upgrades/TimelockedUpgradeable.sol"; - -/// @dev https://community.optimism.io/docs/protocol/protocol-2.0/#l1block -interface L1BlockPrecompile { - function number() external view returns (uint64); - function timestamp() external view returns (uint64); - function hash() external view returns (bytes32); -} - -/// @title StorageOracle -/// @notice Stores slot values of L1 accounts. -contract StorageOracle is TimelockedUpgradeable { - /// @notice Represents a storage slot value on L1, with the block number it was retrieved from. - struct StorageSlot { - bytes32 value; - uint256 blockNumber; - } - - /// @dev https://community.optimism.io/docs/developers/build/differences/#opcode-differences - L1BlockPrecompile public constant L1_BLOCK = L1BlockPrecompile(0x4200000000000000000000000000000000000015); - address public gateway; - bytes32 public functionId; - /// @notice Mapping for L1 account -> storage slot number -> storage slot value. - mapping(address => mapping(uint256 => StorageSlot)) public slots; - - event SlotRequested(uint256 indexed blockNumber, bytes32 indexed blockHash, address indexed account, uint256 slot); - event SlotUpdated(uint256 indexed blockNumber, address indexed account, uint256 slot, bytes32 value); - - error InvalidL1BlockHash(); - error InvalidL1BlockNumber(); - error NotFromFunctionGateway(address sender); - error OutdatedBlockNumber(uint256 blockNumber, uint256 storedBlockNumber); - - /// @param _gateway The FunctionGateway address. - /// @param _functionId The functionId for the storage verifier. - function initialize(address _gateway, bytes32 _functionId, address _timelock, address _guardian) - external - initializer - { - gateway = _gateway; - functionId = _functionId; - __TimelockedUpgradeable_init(_timelock, _guardian); - } - - /// @notice Request a storage slot value for a given account on L1. - function requestStorageSlot(address _account, uint256 _slot) external payable returns (bytes32 requestId) { - bytes32 blockHash = L1_BLOCK.hash(); - if (blockHash == bytes32(0)) { - revert InvalidL1BlockHash(); - } - uint256 blockNumber = L1_BLOCK.number(); - if (blockNumber == 0) { - revert InvalidL1BlockNumber(); - } - - bytes memory input = abi.encode(blockHash, _account, _slot); - bytes memory context = abi.encode(blockNumber, _account, _slot); - requestId = IFunctionGateway(gateway).request{value: msg.value}( - functionId, input, StorageOracle.handleStorageSlot.selector, context - ); - - emit SlotRequested(blockNumber, blockHash, _account, _slot); - } - - /// @dev Callback function to recieve the storage slot value from the FunctionGateway. If for existing slot, MUST update - /// for a more recent blockNumber. - function handleStorageSlot(bytes memory _output, bytes memory _context) external { - if (msg.sender != gateway) { - revert NotFromFunctionGateway(msg.sender); - } - - bytes32 slotValue = abi.decode(_output, (bytes32)); - (uint256 blockNumber, address account, uint256 slot) = abi.decode(_context, (uint256, address, uint256)); - if (blockNumber <= slots[account][slot].blockNumber) { - revert OutdatedBlockNumber(blockNumber, slots[account][slot].blockNumber); - } - - slots[account][slot] = StorageSlot(slotValue, blockNumber); - - emit SlotUpdated(blockNumber, account, slot, slotValue); - } -} diff --git a/contracts/src/examples/storage/StorageVerifier.sol b/contracts/src/examples/storage/StorageVerifier.sol deleted file mode 100644 index a7d126e07..000000000 --- a/contracts/src/examples/storage/StorageVerifier.sol +++ /dev/null @@ -1,576 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -library Pairing { - uint256 constant PRIME_Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; - - struct G1Point { - uint256 X; - uint256 Y; - } - - // Encoding of field elements is: X[0] * z + X[1] - struct G2Point { - uint256[2] X; - uint256[2] Y; - } - - /* - * @return The negation of p, i.e. p.plus(p.negate()) should be zero. - */ - function negate(G1Point memory p) internal pure returns (G1Point memory) { - // The prime q in the base field F_q for G1 - if (p.X == 0 && p.Y == 0) { - return G1Point(0, 0); - } else { - return G1Point(p.X, PRIME_Q - (p.Y % PRIME_Q)); - } - } - - /* - * @return The sum of two points of G1 - */ - function plus(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) { - uint256[4] memory input; - input[0] = p1.X; - input[1] = p1.Y; - input[2] = p2.X; - input[3] = p2.Y; - bool success; - - // solium-disable-next-line security/no-inline-assembly - assembly { - success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60) - // Use "invalid" to make gas estimation work - switch success - case 0 { invalid() } - } - - require(success, "pairing-add-failed"); - } - - /* - * Same as plus but accepts raw input instead of struct - * @return The sum of two points of G1, one is represented as array - */ - function plus_raw(uint256[4] memory input, G1Point memory r) internal view { - bool success; - - // solium-disable-next-line security/no-inline-assembly - assembly { - success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60) - // Use "invalid" to make gas estimation work - switch success - case 0 { invalid() } - } - - require(success, "pairing-add-failed"); - } - - /* - * @return The product of a point on G1 and a scalar, i.e. - * p == p.scalar_mul(1) and p.plus(p) == p.scalar_mul(2) for all - * points p. - */ - function scalar_mul(G1Point memory p, uint256 s) internal view returns (G1Point memory r) { - uint256[3] memory input; - input[0] = p.X; - input[1] = p.Y; - input[2] = s; - bool success; - // solium-disable-next-line security/no-inline-assembly - assembly { - success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60) - // Use "invalid" to make gas estimation work - switch success - case 0 { invalid() } - } - require(success, "pairing-mul-failed"); - } - - /* - * Same as scalar_mul but accepts raw input instead of struct, - * Which avoid extra allocation. provided input can be allocated outside and re-used multiple times - */ - function scalar_mul_raw(uint256[3] memory input, G1Point memory r) internal view { - bool success; - - // solium-disable-next-line security/no-inline-assembly - assembly { - success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60) - // Use "invalid" to make gas estimation work - switch success - case 0 { invalid() } - } - require(success, "pairing-mul-failed"); - } - - /* @return The result of computing the pairing check - * e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1 - * For example, - * pairing([P1(), P1().negate()], [P2(), P2()]) should return true. - */ - function pairing( - G1Point memory a1, - G2Point memory a2, - G1Point memory b1, - G2Point memory b2, - G1Point memory c1, - G2Point memory c2, - G1Point memory d1, - G2Point memory d2 - ) internal view returns (bool) { - G1Point[4] memory p1 = [a1, b1, c1, d1]; - G2Point[4] memory p2 = [a2, b2, c2, d2]; - uint256 inputSize = 24; - uint256[] memory input = new uint256[](inputSize); - - for (uint256 i = 0; i < 4; i++) { - uint256 j = i * 6; - input[j + 0] = p1[i].X; - input[j + 1] = p1[i].Y; - input[j + 2] = p2[i].X[0]; - input[j + 3] = p2[i].X[1]; - input[j + 4] = p2[i].Y[0]; - input[j + 5] = p2[i].Y[1]; - } - - uint256[1] memory out; - bool success; - - // solium-disable-next-line security/no-inline-assembly - assembly { - success := staticcall(sub(gas(), 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) - // Use "invalid" to make gas estimation work - switch success - case 0 { invalid() } - } - - require(success, "pairing-opcode-failed"); - - return out[0] != 0; - } -} - -contract Verifier { - using Pairing for *; - - uint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617; - uint256 constant PRIME_Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; - - struct VerifyingKey { - Pairing.G1Point alfa1; - Pairing.G2Point beta2; - Pairing.G2Point gamma2; - Pairing.G2Point delta2; - } - // []G1Point IC (K in gnark) appears directly in verifyProof - - struct Proof { - Pairing.G1Point A; - Pairing.G2Point B; - Pairing.G1Point C; - } - - function verifyingKey() internal pure returns (VerifyingKey memory vk) { - vk.alfa1 = Pairing.G1Point( - uint256(15065378376707638670416117646191938546464823528318298434911407668648410017312), - uint256(14328565780794488154843107537696396004559344718567701918290331837021769695183) - ); - vk.beta2 = Pairing.G2Point( - [ - uint256(21608662413593678936351578876605429104372744341332808284734169211800668886021), - uint256(14272630991227820574186833459180341377383838929920263355368708236729516236510) - ], - [ - uint256(16641043772513434533950209102074465229233476042166934559766744767810330184564), - uint256(6162122694319393529287233670241265074511780247270252331117359314308552821119) - ] - ); - vk.gamma2 = Pairing.G2Point( - [ - uint256(13132182365077749935258621721022525042673781526193917683715236922498527090287), - uint256(15561074370462920423820148502023399216464240426394708700564724325660560082718) - ], - [ - uint256(10082726381035042218296813991627285842615800319245653642200496444791944486189), - uint256(19936166073830122769051017946410845224800149361868042760143437401219984978115) - ] - ); - vk.delta2 = Pairing.G2Point( - [ - uint256(18835698337094098366375289269375058880930688910548530995640100337968257621142), - uint256(2538885030664125768153917843471118992747126086079950113951128163711148595911) - ], - [ - uint256(3381368293223064763369350882484383507924963445101730404619590717560533944931), - uint256(20044872545096760477413396293539672831863209972531251378473847402381937985325) - ] - ); - } - - // accumulate scalarMul(mul_input) into q - // that is computes sets q = (mul_input[0:2] * mul_input[3]) + q - function accumulate( - uint256[3] memory mul_input, - Pairing.G1Point memory p, - uint256[4] memory buffer, - Pairing.G1Point memory q - ) internal view { - // computes p = mul_input[0:2] * mul_input[3] - Pairing.scalar_mul_raw(mul_input, p); - - // point addition inputs - buffer[0] = q.X; - buffer[1] = q.Y; - buffer[2] = p.X; - buffer[3] = p.Y; - - // q = p + q - Pairing.plus_raw(buffer, q); - } - - /* - * @returns Whether the proof is valid given the hardcoded verifying key - * above and the public inputs - */ - function verifyProof(uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c, uint256[65] memory input) - public - view - returns (bool r) - { - Proof memory proof; - proof.A = Pairing.G1Point(a[0], a[1]); - proof.B = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]); - proof.C = Pairing.G1Point(c[0], c[1]); - - // Make sure that proof.A, B, and C are each less than the prime q - require(proof.A.X < PRIME_Q, "verifier-aX-gte-prime-q"); - require(proof.A.Y < PRIME_Q, "verifier-aY-gte-prime-q"); - - require(proof.B.X[0] < PRIME_Q, "verifier-bX0-gte-prime-q"); - require(proof.B.Y[0] < PRIME_Q, "verifier-bY0-gte-prime-q"); - - require(proof.B.X[1] < PRIME_Q, "verifier-bX1-gte-prime-q"); - require(proof.B.Y[1] < PRIME_Q, "verifier-bY1-gte-prime-q"); - - require(proof.C.X < PRIME_Q, "verifier-cX-gte-prime-q"); - require(proof.C.Y < PRIME_Q, "verifier-cY-gte-prime-q"); - - // Make sure that every input is less than the snark scalar field - for (uint256 i = 0; i < input.length; i++) { - require(input[i] < SNARK_SCALAR_FIELD, "verifier-gte-snark-scalar-field"); - } - - VerifyingKey memory vk = verifyingKey(); - - // Compute the linear combination vk_x - Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0); - - // Buffer reused for addition p1 + p2 to avoid memory allocations - // [0:2] -> p1.X, p1.Y ; [2:4] -> p2.X, p2.Y - uint256[4] memory add_input; - - // Buffer reused for multiplication p1 * s - // [0:2] -> p1.X, p1.Y ; [3] -> s - uint256[3] memory mul_input; - - // temporary point to avoid extra allocations in accumulate - Pairing.G1Point memory q = Pairing.G1Point(0, 0); - - vk_x.X = uint256(7654151173307285122173887557943556592926627323803440265411428835933171698030); // vk.K[0].X - vk_x.Y = uint256(1267569108851906122418933906145913022663962383604792269197553633453069852082); // vk.K[0].Y - mul_input[0] = uint256(0); // vk.K[1].X - mul_input[1] = uint256(0); // vk.K[1].Y - mul_input[2] = input[0]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[1] * input[0] - mul_input[0] = uint256(10855663286981623084541363489660102193206622537607772833968317321581433303751); // vk.K[2].X - mul_input[1] = uint256(12156643609098206979852635788280459246023978138921482912702542075055217047953); // vk.K[2].Y - mul_input[2] = input[1]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[2] * input[1] - mul_input[0] = uint256(379076147614366186237852555128877932752707022181195558773951575810360280983); // vk.K[3].X - mul_input[1] = uint256(20275768584033756898412813982387176725473685447816316945827890314022804466668); // vk.K[3].Y - mul_input[2] = input[2]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[3] * input[2] - mul_input[0] = uint256(2030788471383854807393572254897579868967448362247501984749898450508158620589); // vk.K[4].X - mul_input[1] = uint256(16007079715104718539427533809679786172137912244729461946995485300671697674877); // vk.K[4].Y - mul_input[2] = input[3]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[4] * input[3] - mul_input[0] = uint256(3659729532935328078600286048545654261948161883356705951517335433023302604447); // vk.K[5].X - mul_input[1] = uint256(6719541045159043658238314026173320015187154961043383047031507241065433979987); // vk.K[5].Y - mul_input[2] = input[4]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[5] * input[4] - mul_input[0] = uint256(9023351031242744707107208505085543026451788790872710445827418724631815295840); // vk.K[6].X - mul_input[1] = uint256(2498974708525416644646883774124922731192136194723500432208844468584751225497); // vk.K[6].Y - mul_input[2] = input[5]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[6] * input[5] - mul_input[0] = uint256(11760246946898200849775229670108235157754487907263669813035215235872743186597); // vk.K[7].X - mul_input[1] = uint256(5382428339030687870768870582444025050484374185231261099126636032475175446148); // vk.K[7].Y - mul_input[2] = input[6]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[7] * input[6] - mul_input[0] = uint256(332103316032981202977921170491728275515984536882295042122024740487031669015); // vk.K[8].X - mul_input[1] = uint256(484223038059012831998672398465994235268759953393977542517196949254233028660); // vk.K[8].Y - mul_input[2] = input[7]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[8] * input[7] - mul_input[0] = uint256(5344906529970141689021459145557374163117422738842071706750631467728871290394); // vk.K[9].X - mul_input[1] = uint256(7731978403516757842874921595990408683343135883653940410950541995815224341199); // vk.K[9].Y - mul_input[2] = input[8]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[9] * input[8] - mul_input[0] = uint256(10362237886978658404784044741070389359500890596626548033780244659029433510363); // vk.K[10].X - mul_input[1] = uint256(6285629694982155865291087094189363562595967452963101197020929967022416193184); // vk.K[10].Y - mul_input[2] = input[9]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[10] * input[9] - mul_input[0] = uint256(1936826942872850266674041622347967683160440267203145838962497651901744863132); // vk.K[11].X - mul_input[1] = uint256(2489418929250071077827953016163896767277738430716133365272418875838627300251); // vk.K[11].Y - mul_input[2] = input[10]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[11] * input[10] - mul_input[0] = uint256(12779474367520445587507333272472534286610205070395166091355451386189619020759); // vk.K[12].X - mul_input[1] = uint256(16098399295897998668449640624417961627391582297976508801357763570695142130577); // vk.K[12].Y - mul_input[2] = input[11]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[12] * input[11] - mul_input[0] = uint256(443172960809137696796573525061835890990476988281640266727036593096513946387); // vk.K[13].X - mul_input[1] = uint256(20448435027686077373503601710307109999095366634908587134616976911597013705326); // vk.K[13].Y - mul_input[2] = input[12]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[13] * input[12] - mul_input[0] = uint256(4420010271881666237419507746577855992446973907995876983937642148718830707448); // vk.K[14].X - mul_input[1] = uint256(14540506650087850032683132977210992280987068520451687156325445797696065869484); // vk.K[14].Y - mul_input[2] = input[13]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[14] * input[13] - mul_input[0] = uint256(19641835005247180332480402296715294035949028476829642551362696889499513656838); // vk.K[15].X - mul_input[1] = uint256(4812315591576788861668368040515410531600872313469076363556584755378733696050); // vk.K[15].Y - mul_input[2] = input[14]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[15] * input[14] - mul_input[0] = uint256(12640577748972357982630117727971303258087585863699713717297881582503076631360); // vk.K[16].X - mul_input[1] = uint256(13065923353823232570476651439967308146274765135151428476341066795511706991767); // vk.K[16].Y - mul_input[2] = input[15]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[16] * input[15] - mul_input[0] = uint256(13572128760084308415140083506753360673600577607804820189016855697861704739224); // vk.K[17].X - mul_input[1] = uint256(8442833044896943902431485896013816816589701482716364853929712353957738745885); // vk.K[17].Y - mul_input[2] = input[16]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[17] * input[16] - mul_input[0] = uint256(12782767107221283109044396047775873882831103174902550450883267206197174805868); // vk.K[18].X - mul_input[1] = uint256(21725909149821822419863341739266801796457530684451541722014143306092290491812); // vk.K[18].Y - mul_input[2] = input[17]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[18] * input[17] - mul_input[0] = uint256(11078573045918050069962548128864339547899985435179862834648073403084209835710); // vk.K[19].X - mul_input[1] = uint256(12399059488837415085805609005448464807782897587253414030053853866684873097988); // vk.K[19].Y - mul_input[2] = input[18]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[19] * input[18] - mul_input[0] = uint256(10315226201173711467954752250803493769599555861590514433803248756358327104145); // vk.K[20].X - mul_input[1] = uint256(2856544295114544565653429320946926740804556743379163983013096592795845303539); // vk.K[20].Y - mul_input[2] = input[19]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[20] * input[19] - mul_input[0] = uint256(9354895592827270566590945984304896833859741287021261458869270672256004059535); // vk.K[21].X - mul_input[1] = uint256(15011309793775328188185572246572377707679615478035837762242785740323839285319); // vk.K[21].Y - mul_input[2] = input[20]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[21] * input[20] - mul_input[0] = uint256(13313466138074340718734302586098076097388950008677954748589938155741454888448); // vk.K[22].X - mul_input[1] = uint256(12353745256729266438311891904289828780910344800526689870927542307621168813347); // vk.K[22].Y - mul_input[2] = input[21]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[22] * input[21] - mul_input[0] = uint256(15190018048332196524754887079224540675648717818816895400470708784186351975840); // vk.K[23].X - mul_input[1] = uint256(10147458378909811594952055908189722911538701320475523176144463017748535907490); // vk.K[23].Y - mul_input[2] = input[22]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[23] * input[22] - mul_input[0] = uint256(234614104392190853693722220259832416753154027782029485053737056100888951760); // vk.K[24].X - mul_input[1] = uint256(4128702334020980420987327656543100690673142825029758802716705558844651759585); // vk.K[24].Y - mul_input[2] = input[23]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[24] * input[23] - mul_input[0] = uint256(6931986590268588882910380631925893379786131874131718051994417017802935487518); // vk.K[25].X - mul_input[1] = uint256(6553771184053803320674257601817296516132168924473495362665037590748879926835); // vk.K[25].Y - mul_input[2] = input[24]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[25] * input[24] - mul_input[0] = uint256(8007641449250544351042554455733868623978825618215306263257441983965247015306); // vk.K[26].X - mul_input[1] = uint256(6989427805525814667453773033842061928861369548889935848958642430130423311990); // vk.K[26].Y - mul_input[2] = input[25]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[26] * input[25] - mul_input[0] = uint256(14741810725607764328249036718716826447801414725797362707614991969593535198061); // vk.K[27].X - mul_input[1] = uint256(16924891809278267680585602860764437386367597260415854373705866086335127810942); // vk.K[27].Y - mul_input[2] = input[26]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[27] * input[26] - mul_input[0] = uint256(19606675076775461784511771066572876373775296642178524644407593031446474991396); // vk.K[28].X - mul_input[1] = uint256(8606522840804950948717310490003731381536956837776527018324136881608861581571); // vk.K[28].Y - mul_input[2] = input[27]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[28] * input[27] - mul_input[0] = uint256(3378778428452374523256569312957451002365689609349537175414837663286905789890); // vk.K[29].X - mul_input[1] = uint256(3398091315042692109385568436973712260471414367803233969505626729524803304405); // vk.K[29].Y - mul_input[2] = input[28]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[29] * input[28] - mul_input[0] = uint256(8552650451497299813794466582330968619836679761737303659681933318167757098631); // vk.K[30].X - mul_input[1] = uint256(4217931479579097251137035220978681356363760563375323313336646382986482561900); // vk.K[30].Y - mul_input[2] = input[29]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[30] * input[29] - mul_input[0] = uint256(17389761499517884028227459747393901628845657128749005600031578978917606598569); // vk.K[31].X - mul_input[1] = uint256(10555185012236734284382729900325079069840722015806083080596709578503001010042); // vk.K[31].Y - mul_input[2] = input[30]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[31] * input[30] - mul_input[0] = uint256(20522064923903915435529181641985382408182131990229432495749925727116732333618); // vk.K[32].X - mul_input[1] = uint256(9262127328114327567334564923775981849508792353488856435505031509658876768785); // vk.K[32].Y - mul_input[2] = input[31]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[32] * input[31] - mul_input[0] = uint256(0); // vk.K[33].X - mul_input[1] = uint256(0); // vk.K[33].Y - mul_input[2] = input[32]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[33] * input[32] - mul_input[0] = uint256(19805515723576526151865962480176526559600946331940416602919435733744559178939); // vk.K[34].X - mul_input[1] = uint256(14436323825307532673910662135739037295632234829812967405189138584329725932226); // vk.K[34].Y - mul_input[2] = input[33]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[34] * input[33] - mul_input[0] = uint256(19769937692070903973717952756328400818768446873200827647850618096003799853020); // vk.K[35].X - mul_input[1] = uint256(21577770339510253918286877921192503157062550953375939162858739967204290523211); // vk.K[35].Y - mul_input[2] = input[34]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[35] * input[34] - mul_input[0] = uint256(21463274337361306731827127358497242847186037166889108461214045419815817218996); // vk.K[36].X - mul_input[1] = uint256(19499490089855815631318730286338300201490444832730925605965665171488963647858); // vk.K[36].Y - mul_input[2] = input[35]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[36] * input[35] - mul_input[0] = uint256(12057739572080112380123927889780603267198763016607327963671783717329310186493); // vk.K[37].X - mul_input[1] = uint256(7303684643153206320562424737389940301747294453769658376891530120300287091977); // vk.K[37].Y - mul_input[2] = input[36]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[37] * input[36] - mul_input[0] = uint256(17217188987453618497424883038450136632316646488983452367886954124919864036693); // vk.K[38].X - mul_input[1] = uint256(21375339730127974465467984229113021398656189521351737743163893047555883800246); // vk.K[38].Y - mul_input[2] = input[37]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[38] * input[37] - mul_input[0] = uint256(18787439887787093780339026828453522129057912122177599159715079795672616250109); // vk.K[39].X - mul_input[1] = uint256(17851621594125688853191944994514545725947854063365545119007748240805316325955); // vk.K[39].Y - mul_input[2] = input[38]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[39] * input[38] - mul_input[0] = uint256(15022035693900431687276953568986992848817580330708047655879922986997313472221); // vk.K[40].X - mul_input[1] = uint256(20284983706070006505302341041678459987145987163750240764970385624811896664406); // vk.K[40].Y - mul_input[2] = input[39]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[40] * input[39] - mul_input[0] = uint256(17682250282074192986606512022644465366834162256038110695035322304798987194845); // vk.K[41].X - mul_input[1] = uint256(17735039760536327883984565482595346927072649564075439600588336978864313757679); // vk.K[41].Y - mul_input[2] = input[40]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[41] * input[40] - mul_input[0] = uint256(20899706779328863341678425647248526006380374041381805254108969921590054971843); // vk.K[42].X - mul_input[1] = uint256(9208903989072050237486846027857559959173926655646571064322647318415126307423); // vk.K[42].Y - mul_input[2] = input[41]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[42] * input[41] - mul_input[0] = uint256(8094119844233180842261868250217351476703160601947508218059277542084472590858); // vk.K[43].X - mul_input[1] = uint256(3931401739387971212950794367903322610453707604654345792724304050982429234275); // vk.K[43].Y - mul_input[2] = input[42]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[43] * input[42] - mul_input[0] = uint256(1316264156504633102498105591347442946770583029642110683067801761935109545631); // vk.K[44].X - mul_input[1] = uint256(6410737200033529651526204670194859866494250065115817937275936426766906855619); // vk.K[44].Y - mul_input[2] = input[43]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[44] * input[43] - mul_input[0] = uint256(8804621950111225410125455844142464146394958064668792060504877361795418468316); // vk.K[45].X - mul_input[1] = uint256(8580620024820260438211068784935002090479952452161813928224108672526860866015); // vk.K[45].Y - mul_input[2] = input[44]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[45] * input[44] - mul_input[0] = uint256(7112295527738970285127563356966652173102917507489227391418611658263599307482); // vk.K[46].X - mul_input[1] = uint256(17275281338238142402668320571083598275071996182405634500711023887464421538127); // vk.K[46].Y - mul_input[2] = input[45]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[46] * input[45] - mul_input[0] = uint256(5240121977703409724976930147474666123582523807199050824430926013248898323413); // vk.K[47].X - mul_input[1] = uint256(9235777244560018425574571644168716210830462792585067951593424650639702291943); // vk.K[47].Y - mul_input[2] = input[46]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[47] * input[46] - mul_input[0] = uint256(16709515988692486378095964497727607992954421154155836143184835325120234108282); // vk.K[48].X - mul_input[1] = uint256(4318821262168551260213596218763477445736619275692986821452072174624316039747); // vk.K[48].Y - mul_input[2] = input[47]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[48] * input[47] - mul_input[0] = uint256(4635653803757786734812939730130448826232706399998169438201812455241736781365); // vk.K[49].X - mul_input[1] = uint256(10620534372183167886846599595246470641725726870973800884133180230395135737336); // vk.K[49].Y - mul_input[2] = input[48]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[49] * input[48] - mul_input[0] = uint256(21882091146466759727378676055635488784699217830186438786659067805274266463217); // vk.K[50].X - mul_input[1] = uint256(18598242203333244012781528775935406341731159877256787836648474120945984728668); // vk.K[50].Y - mul_input[2] = input[49]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[50] * input[49] - mul_input[0] = uint256(4981598058944746539451200624832095463060756413653505740624778630043872771559); // vk.K[51].X - mul_input[1] = uint256(15417437381372953121848338347341631007478788246258161716837437944605430967710); // vk.K[51].Y - mul_input[2] = input[50]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[51] * input[50] - mul_input[0] = uint256(16449857651479430087361783294716085780818735843608843357258053633847274952841); // vk.K[52].X - mul_input[1] = uint256(15723174467364037738901289426375812656268714827433964282590968293223190370878); // vk.K[52].Y - mul_input[2] = input[51]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[52] * input[51] - mul_input[0] = uint256(20648916574105536651189253176665249822733862047163598918925707075866654074662); // vk.K[53].X - mul_input[1] = uint256(21287059011152424060114653424447126287308325233923052797964482922876748269568); // vk.K[53].Y - mul_input[2] = input[52]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[53] * input[52] - mul_input[0] = uint256(18585476542396457205150744199897004875593607482225637447845157197513269605578); // vk.K[54].X - mul_input[1] = uint256(3417167586405724706465908229613681922657557710181148039128574753784005202656); // vk.K[54].Y - mul_input[2] = input[53]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[54] * input[53] - mul_input[0] = uint256(4511397141251924031887085372482825080786918659993462057314369239464754481694); // vk.K[55].X - mul_input[1] = uint256(21717095464432043238756681501430279756357661473638833021102155654431510563342); // vk.K[55].Y - mul_input[2] = input[54]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[55] * input[54] - mul_input[0] = uint256(9212519189230801322001536903365645225220584836288401322046467666908189548807); // vk.K[56].X - mul_input[1] = uint256(19744538517056645677142028979018732961431154170994932788904230767809445689768); // vk.K[56].Y - mul_input[2] = input[55]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[56] * input[55] - mul_input[0] = uint256(12289453430414039567836724210064005227666479474586979621733298761776796474516); // vk.K[57].X - mul_input[1] = uint256(12989757651650597082755681430685414608745195391709803644101621833221841663099); // vk.K[57].Y - mul_input[2] = input[56]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[57] * input[56] - mul_input[0] = uint256(2369478084041109780531328278734355652837607008951232860940114157378030098765); // vk.K[58].X - mul_input[1] = uint256(6119868655329830957213547984204983011004726394242293527463828569451316899897); // vk.K[58].Y - mul_input[2] = input[57]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[58] * input[57] - mul_input[0] = uint256(17989837724212112366551871898291137740340429905303785911117451851352882896345); // vk.K[59].X - mul_input[1] = uint256(17949950156855941131881511270898739855917513493341349952799783132793577741533); // vk.K[59].Y - mul_input[2] = input[58]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[59] * input[58] - mul_input[0] = uint256(7262439193785268583033241221853354235600977055409379173808433414317405448832); // vk.K[60].X - mul_input[1] = uint256(12203906070920291015993347316731095119713139475700145895368333405554307230470); // vk.K[60].Y - mul_input[2] = input[59]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[60] * input[59] - mul_input[0] = uint256(1162813742019157110963043810774081780095578126075902578179759093147701028966); // vk.K[61].X - mul_input[1] = uint256(6196461946796674808960015791266782945323722628464646545853640633136894953642); // vk.K[61].Y - mul_input[2] = input[60]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[61] * input[60] - mul_input[0] = uint256(8734960838152226512446036029393702945097778032815532218825582662229148105809); // vk.K[62].X - mul_input[1] = uint256(14156597841489472902105242066512520003665698393998522446948180722237464995747); // vk.K[62].Y - mul_input[2] = input[61]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[62] * input[61] - mul_input[0] = uint256(4584525156462878436907385844466134332162203762915420480339839395820190826598); // vk.K[63].X - mul_input[1] = uint256(20896772351738173920864818723101902251047201025669140610634794223821078661262); // vk.K[63].Y - mul_input[2] = input[62]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[63] * input[62] - mul_input[0] = uint256(15548856620589266889065140246191848830841596843403455464590867915077143726220); // vk.K[64].X - mul_input[1] = uint256(19703685940179675295187023238588296384286868782044376229887047852708735602340); // vk.K[64].Y - mul_input[2] = input[63]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[64] * input[63] - mul_input[0] = uint256(6512240350257283986195670322307359040229223793918266787712417443520969192740); // vk.K[65].X - mul_input[1] = uint256(17883424236536710893435059391856918208546300448278439854180388920157605103236); // vk.K[65].Y - mul_input[2] = input[64]; - accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[65] * input[64] - - return - Pairing.pairing(Pairing.negate(proof.A), proof.B, vk.alfa1, vk.beta2, vk_x, vk.gamma2, proof.C, vk.delta2); - } -} - -interface IFunctionVerifier { - function verify(bytes32 _inputHash, bytes32 _outputHash, bytes memory _proof) external view returns (bool); - - function verificationKeyHash() external pure returns (bytes32); -} - -contract StorageVerifier is IFunctionVerifier, Verifier { - function verify(bytes32 _inputHash, bytes32 _outputHash, bytes memory _proof) external pure returns (bool) { - (uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c) = - abi.decode(_proof, (uint256[2], uint256[2][2], uint256[2])); - - uint256[65] memory input; - input[0] = uint256(_inputHash); - input[1] = uint256(_outputHash); - - // remove unused warnings - a = a; - b = b; - c = c; - // temporary, should do: - // return verifyProof(a, b, c, input); - return true; - } - - function verificationKeyHash() external pure returns (bytes32) { - return keccak256(abi.encode(verifyingKey())); - } -} diff --git a/contracts/src/interfaces/IFunctionGateway.sol b/contracts/src/interfaces/IFunctionGateway.sol index 81209fe0f..2a8813f57 100644 --- a/contracts/src/interfaces/IFunctionGateway.sol +++ b/contracts/src/interfaces/IFunctionGateway.sol @@ -1,91 +1,63 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.5.0; - -struct FunctionRequest { - bytes32 functionId; - bytes32 inputHash; - bytes32 outputHash; - bytes32 contextHash; - address callbackAddress; - bytes4 callbackSelector; - bool proofFulfilled; - bool callbackFulfilled; -} +pragma solidity >=0.8.0; interface IFunctionGatewayEvents { - event ProofRequested( - uint256 indexed nonce, + event Request( + uint32 indexed nonce, bytes32 indexed functionId, - bytes32 requestId, - bytes inputs, + bytes input, bytes context, - uint256 gasLimit, - uint256 feeAmount + bytes4 callbackSelector, + uint32 callbackGasLimit + ); + event RequestFulfilled( + uint32 indexed nonce, + bytes32 indexed functionId, + bytes32 inputHash, + bytes32 outputHash ); - event ProofFulfilled(bytes32 requestId, bytes32 outputHash, bytes proof); - event ProofBatchFulfilled( - bytes32[] requestIds, - bytes aggregateProof, - bytes32 inputsRoot, - bytes32[] outputHashes, - bytes32 outputsRoot, - bytes32 verificationKeyRoot + event Call( + bytes32 indexed functionId, + bytes32 inputHash, + bytes32 outputHash ); - event CallbackFulfilled(bytes32 requestId, bytes output, bytes context); - event ScalarUpdated(uint256 scalar); } interface IFunctionGatewayErrors { - error RequestNotFound(bytes32 requestId); - error ContextMismatch(bytes32 contextHash, bytes context); - error OutputMismatch(bytes32 outputHash, bytes context); - error InputsRootMismatch(bytes32 inputsRoot, bytes32[] inputHashes); - error OutputsRootMismatch(bytes32 outputsRoot, bytes32[] outputHashes); - error VerificationKeysRootMismatch(bytes32 outputsRoot, bytes32[] outputHashes); - error ProofNotFulfilled(bytes32 requestId); - error ProofAlreadyFulfilled(bytes32 requestId); - error InvalidProof(address verifier, bytes32 inputHash, bytes32 outputHash, bytes proof); - error CallbackFailed(address callbackAddress, bytes4 callbackSelector); - error CallbackAlreadyFulfilled(bytes32 requestId); - error LengthMismatch(uint256 expected, uint256 actual); - error InsufficientFeeAmount(uint256 expected, uint256 actual); - error RefundFailed(address refundAccount, uint256 refundAmount); + error InvalidRequest( + uint32 nonce, + bytes32 expectedRequestHash, + bytes32 requestHash + ); + error CallbackFailed(bytes4 callbackSelector, bytes output, bytes context); + error InvalidCall(bytes32 functionId, bytes32 inputHash); + error CallFailed(address callbackAddress, bytes callbackData); + error InvalidProof( + address verifier, + bytes32 inputHash, + bytes32 outputHash, + bytes proof + ); } interface IFunctionGateway is IFunctionGatewayEvents, IFunctionGatewayErrors { - function requests(bytes32 requestId) - external - view - returns (bytes32, bytes32, bytes32, bytes32, address, bytes4, bool, bool); - - function request(bytes32 functionId, bytes memory input, bytes4 callbackSelector, bytes memory context) - external - payable - returns (bytes32); - - function request( - bytes32 functionId, - bytes memory input, - bytes4 callbackSelector, - bytes memory context, - uint256 gasLimit, - address refundAccount - ) external payable returns (bytes32); - - function fulfill(bytes32 requestId, bytes32 outputHash, bytes memory proof) external; - - function fulfillBatch( - bytes32[] memory requestIds, - bytes memory aggregateProof, - bytes32 inputsRoot, - bytes32[] memory outputHashes, - bytes32 outputsRoot, - bytes32 verificationKeyRoot - ) external; - - function callback(bytes32 requestId, bytes memory output, bytes memory context) external; - - function calculateFeeAmount() external view returns (uint256); - - function calculateFeeAmount(uint256 gasLimit) external view returns (uint256); + function zkRequest( + bytes32 _functionId, + bytes memory _input, + bytes memory _context, + bytes4 _callbackSelector + ) external returns (bytes32); + + function zkRequest( + bytes32 _functionId, + bytes memory _input, + bytes memory _context, + bytes4 _callbackSelector, + uint32 _callbackGasLimit + ) external returns (bytes32); + + function zkCall( + bytes32 _functionId, + bytes memory _input + ) external view returns (bytes memory); } diff --git a/contracts/src/mocks/MockFunctionGateway.sol b/contracts/src/mocks/MockFunctionGateway.sol deleted file mode 100644 index f79098190..000000000 --- a/contracts/src/mocks/MockFunctionGateway.sol +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -import {VmSafe} from "forge-std/Vm.sol"; -import {stdJson} from "forge-std/StdJson.sol"; -import {IFunctionGateway, FunctionRequest} from "../interfaces/IFunctionGateway.sol"; - -contract MockFunctionGateway is IFunctionGateway { - VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); - uint256 public DEFAULT_GAS_LIMIT = 1000000; - uint256 public nonce; - uint256 public scalar = 1; - mapping(bytes32 => FunctionRequest) public requests; - mapping(bytes32 => bytes) public outputs; - - function loadFixture(string memory _path) external { - string memory json; - try vm.readFile(_path) returns (string memory data) { - json = data; - } catch { - revert("MockFunctionGateway: fixture not found"); - } - bytes memory input = stdJson.readBytes(json, "$.input"); - bytes memory output = stdJson.readBytes(json, "$.output"); - outputs[sha256(input)] = output; - } - - function setRequest(bytes32 _requestId, FunctionRequest memory _request) public { - requests[_requestId] = _request; - } - - function request(bytes32 _functionId, bytes memory _input, bytes4 _callbackSelector, bytes memory _context) - external - payable - returns (bytes32) - { - return request(_functionId, _input, _callbackSelector, _context, DEFAULT_GAS_LIMIT, tx.origin); - } - - function request( - bytes32 _functionId, - bytes memory _input, - bytes4 _callbackSelector, - bytes memory _context, - uint256 _gasLimit, - address - ) public payable returns (bytes32) { - bytes32 inputHash = sha256(_input); - bytes32 contextHash = keccak256(_context); - FunctionRequest memory r = FunctionRequest({ - functionId: _functionId, - inputHash: inputHash, - outputHash: bytes32(0), - contextHash: contextHash, - callbackAddress: msg.sender, - callbackSelector: _callbackSelector, - proofFulfilled: false, - callbackFulfilled: false - }); - - bytes32 requestId = keccak256(abi.encode(nonce, r)); - requests[requestId] = r; - - emit ProofRequested(nonce, _functionId, requestId, _input, _context, _gasLimit, calculateFeeAmount(_gasLimit)); - nonce++; - - // If fixture has been pre-loaded, automatically fulfill and callback. - bytes memory output = outputs[inputHash]; - if (output.length > 0) { - r.outputHash = keccak256(output); - r.proofFulfilled = true; - r.callbackFulfilled = true; - - (bool status,) = msg.sender.call(abi.encodeWithSelector(_callbackSelector, output, _context)); - if (!status) { - revert CallbackFailed(msg.sender, _callbackSelector); - } - } - - return requestId; - } - - function fulfill(bytes32 _requestId, bytes32 _outputHash, bytes memory _proof) external { - FunctionRequest storage r = requests[_requestId]; - r.proofFulfilled = true; - r.outputHash = _outputHash; - - emit ProofFulfilled(_requestId, _outputHash, _proof); - } - - function fulfillBatch( - bytes32[] memory _requestIds, - bytes memory _aggregateProof, - bytes32 _inputsRoot, - bytes32[] memory _outputHashes, - bytes32 _outputsRoot, - bytes32 _verificationKeyRoot - ) external { - for (uint256 i = 0; i < _requestIds.length; i++) { - bytes32 requestId = _requestIds[i]; - FunctionRequest storage r = requests[requestId]; - r.proofFulfilled = true; - r.outputHash = _outputHashes[i]; - } - - emit ProofBatchFulfilled( - _requestIds, _aggregateProof, _inputsRoot, _outputHashes, _outputsRoot, _verificationKeyRoot - ); - } - - function callback(bytes32 _requestId, bytes memory _output, bytes memory _context) external { - FunctionRequest storage r = requests[_requestId]; - r.callbackFulfilled = true; - - (bool status,) = r.callbackAddress.call(abi.encodeWithSelector(r.callbackSelector, _output, _context)); - if (!status) { - revert CallbackFailed(r.callbackAddress, r.callbackSelector); - } - - emit CallbackFulfilled(_requestId, _output, _context); - } - - function calculateFeeAmount() external view returns (uint256 feeAmount) { - return calculateFeeAmount(DEFAULT_GAS_LIMIT); - } - - function calculateFeeAmount(uint256 _gasLimit) public view returns (uint256 feeAmount) { - if (scalar == 0) { - feeAmount = tx.gasprice * _gasLimit; - } else { - feeAmount = tx.gasprice * _gasLimit * scalar; - } - } - - function setScalar(uint256 _scalar) external { - scalar = _scalar; - - emit ScalarUpdated(scalar); - } -} diff --git a/contracts/src/upgrades/TimelockedUpgradeable.sol b/contracts/src/upgrades/TimelockedUpgradeable.sol index db7e1dfef..594130a19 100644 --- a/contracts/src/upgrades/TimelockedUpgradeable.sol +++ b/contracts/src/upgrades/TimelockedUpgradeable.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.16; -import {Versioned} from "src/upgrades/Versioned.sol"; +import {Versioned} from "./Versioned.sol"; import {Initializable} from "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import {UUPSUpgradeable} from "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import {AccessControlUpgradeable} from "@openzeppelin-upgradeable/contracts/access/AccessControlUpgradeable.sol"; @@ -9,7 +9,12 @@ import {AccessControlUpgradeable} from "@openzeppelin-upgradeable/contracts/acce /// @title TimelockedUpgradeable /// @notice A base contract that has modifiers to specify that certain functions are only callable /// by a sender with a timelock or guardian role. -abstract contract TimelockedUpgradeable is Versioned, Initializable, UUPSUpgradeable, AccessControlUpgradeable { +abstract contract TimelockedUpgradeable is + Versioned, + Initializable, + UUPSUpgradeable, + AccessControlUpgradeable +{ /// @notice A random constant used to identify addresses with the permission of a 'timelock'. /// @dev Should be set to a 'timelock' contract, which may only execute calls after being /// for a certain amount of time. @@ -43,7 +48,10 @@ abstract contract TimelockedUpgradeable is Versioned, Initializable, UUPSUpgrade /// @notice Initializes the contract. /// @dev The DEFAULT_ADMIN_ROLE needs to be set but should be unused. - function __TimelockedUpgradeable_init(address _timelock, address _guardian) internal onlyInitializing { + function __TimelockedUpgradeable_init( + address _timelock, + address _guardian + ) internal onlyInitializing { __AccessControl_init(); __UUPSUpgradeable_init(); _grantRole(DEFAULT_ADMIN_ROLE, _timelock); @@ -52,5 +60,7 @@ abstract contract TimelockedUpgradeable is Versioned, Initializable, UUPSUpgrade } /// @notice Authorizes an upgrade for the implementation contract. - function _authorizeUpgrade(address newImplementation) internal virtual override onlyTimelock {} + function _authorizeUpgrade( + address newImplementation + ) internal virtual override onlyTimelock {} } diff --git a/contracts/test/FunctionGateway.t.sol b/contracts/test/FunctionGateway.t.sol deleted file mode 100644 index ff8cc8363..000000000 --- a/contracts/test/FunctionGateway.t.sol +++ /dev/null @@ -1,288 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -import "forge-std/Vm.sol"; -import "forge-std/console.sol"; -import "forge-std/Test.sol"; - -import {FunctionGateway} from "src/FunctionGateway.sol"; -import { - FunctionRequest, - IFunctionGateway, - IFunctionGatewayEvents, - IFunctionGatewayErrors -} from "src/interfaces/IFunctionGateway.sol"; -import {IFunctionRegistry} from "src/interfaces/IFunctionRegistry.sol"; -import {TestConsumer, AttackConsumer, TestFunctionVerifier} from "test/TestUtils.sol"; -import {Proxy} from "src/upgrades/Proxy.sol"; -import {SuccinctFeeVault} from "src/payments/SuccinctFeeVault.sol"; - -contract FunctionGatewayTest is Test, IFunctionGatewayEvents, IFunctionGatewayErrors { - // Example Function Request and expected values - string internal constant FUNCTION_NAME = "test-verifier"; - bytes32 internal FUNCTION_ID; - bytes internal constant REQUEST = bytes("functionInput"); - bytes4 internal constant CALLBACK_SELECTOR = TestConsumer.handleRequest.selector; - bytes internal constant CALLBACK_CONTEXT = abi.encode(0); - bytes internal constant REQUEST_OUTPUT = abi.encode(true); - bytes32 internal constant REQUEST_OUTPUT_HASH = sha256(REQUEST_OUTPUT); - bytes internal constant REQUEST_PROOF = hex""; - bytes32 internal EXPECTED_REQUEST_ID; - uint256 internal constant DEFAULT_FEE = 0.1 ether; - uint256 internal constant DEFAULT_SCALAR = 1; - - address internal timelock; - address internal guardian; - address payable internal sender; - address internal feeVault; - address internal gateway; - address internal verifier; - address payable internal consumer; - FunctionRequest internal expectedRequest; - - function setUp() public { - timelock = makeAddr("timelock"); - guardian = makeAddr("guardian"); - sender = payable(makeAddr("sender")); - feeVault = address(new SuccinctFeeVault(guardian)); - consumer = payable(address(new TestConsumer())); - - // Deploy FunctionGateway - address gatewayImpl = address(new FunctionGateway()); - gateway = address(new Proxy(gatewayImpl, "")); - FunctionGateway(gateway).initialize(DEFAULT_SCALAR, feeVault, timelock, guardian); - - vm.prank(sender); - (FUNCTION_ID, verifier) = - IFunctionRegistry(gateway).deployAndRegisterFunction(type(TestFunctionVerifier).creationCode, FUNCTION_NAME); - - expectedRequest = FunctionRequest({ - functionId: FUNCTION_ID, - inputHash: sha256(REQUEST), - outputHash: bytes32(0), - contextHash: keccak256(CALLBACK_CONTEXT), - callbackAddress: consumer, - callbackSelector: CALLBACK_SELECTOR, - proofFulfilled: false, - callbackFulfilled: false - }); - EXPECTED_REQUEST_ID = keccak256(abi.encode(FunctionGateway(gateway).nonce(), expectedRequest)); - - vm.deal(sender, DEFAULT_FEE); - vm.deal(consumer, DEFAULT_FEE); - } - - function test_Request_WhenFromCall() public { - uint256 prevNonce = FunctionGateway(gateway).nonce(); - assertEq(prevNonce, 0); - - // Request - vm.expectEmit(true, true, true, true, gateway); - emit ProofRequested( - prevNonce, - FUNCTION_ID, - EXPECTED_REQUEST_ID, - REQUEST, - CALLBACK_CONTEXT, - FunctionGateway(gateway).DEFAULT_GAS_LIMIT(), - 0 - ); - vm.prank(consumer); - bytes32 requestId = FunctionGateway(gateway).request{value: DEFAULT_FEE}( - FUNCTION_ID, REQUEST, CALLBACK_SELECTOR, CALLBACK_CONTEXT - ); - assertEq(EXPECTED_REQUEST_ID, requestId); - - ( - bytes32 functionId, - bytes32 inputHash, - bytes32 outputHash, - bytes32 contextHash, - address callbackAddress, - bytes4 callbackSelector, - bool proofFulfilled, - bool callbackFulfilled - ) = FunctionGateway(gateway).requests(requestId); - assertEq(prevNonce + 1, FunctionGateway(gateway).nonce()); - assertEq(FUNCTION_ID, functionId); - assertEq(sha256(REQUEST), inputHash); - assertEq(bytes32(0), outputHash); - assertEq(keccak256(CALLBACK_CONTEXT), contextHash); - assertEq(address(consumer), callbackAddress); - assertEq(CALLBACK_SELECTOR, callbackSelector); - assertEq(false, proofFulfilled); - assertEq(false, callbackFulfilled); - } - - function test_Request_WhenFromContract() public { - uint256 prevNonce = FunctionGateway(gateway).nonce(); - assertEq(prevNonce, 0); - - // Request - vm.prank(sender); - bytes32 requestId = TestConsumer(payable(address(consumer))).sendRequest{value: DEFAULT_FEE}( - address(gateway), FUNCTION_ID, REQUEST, CALLBACK_SELECTOR, CALLBACK_CONTEXT - ); - assertEq(EXPECTED_REQUEST_ID, requestId); - - ( - bytes32 functionId, - bytes32 inputHash, - bytes32 outputHash, - bytes32 contextHash, - address callbackAddress, - bytes4 callbackSelector, - bool proofFulfilled, - bool callbackFulfilled - ) = FunctionGateway(gateway).requests(requestId); - assertEq(prevNonce + 1, FunctionGateway(gateway).nonce()); - assertEq(FUNCTION_ID, functionId); - assertEq(sha256(REQUEST), inputHash); - assertEq(bytes32(0), outputHash); - assertEq(keccak256(CALLBACK_CONTEXT), contextHash); - assertEq(address(consumer), callbackAddress); - assertEq(CALLBACK_SELECTOR, callbackSelector); - assertEq(false, proofFulfilled); - assertEq(false, callbackFulfilled); - } - - function test_Request_WhenNoFee() public { - uint256 prevNonce = FunctionGateway(gateway).nonce(); - assertEq(prevNonce, 0); - - // Request - vm.expectEmit(true, true, true, true, gateway); - emit ProofRequested( - prevNonce, - FUNCTION_ID, - EXPECTED_REQUEST_ID, - REQUEST, - CALLBACK_CONTEXT, - FunctionGateway(gateway).DEFAULT_GAS_LIMIT(), - 0 - ); - vm.prank(consumer); - bytes32 requestId = FunctionGateway(gateway).request(FUNCTION_ID, REQUEST, CALLBACK_SELECTOR, CALLBACK_CONTEXT); - assertEq(EXPECTED_REQUEST_ID, requestId); - - ( - bytes32 functionId, - bytes32 inputHash, - bytes32 outputHash, - bytes32 contextHash, - address callbackAddress, - bytes4 callbackSelector, - bool proofFulfilled, - bool callbackFulfilled - ) = FunctionGateway(gateway).requests(requestId); - assertEq(prevNonce + 1, FunctionGateway(gateway).nonce()); - assertEq(FUNCTION_ID, functionId); - assertEq(sha256(REQUEST), inputHash); - assertEq(bytes32(0), outputHash); - assertEq(keccak256(CALLBACK_CONTEXT), contextHash); - assertEq(address(consumer), callbackAddress); - assertEq(CALLBACK_SELECTOR, callbackSelector); - assertEq(false, proofFulfilled); - assertEq(false, callbackFulfilled); - } - - function test_Fulfill_WhenFromContract() public { - uint256 prevNonce = FunctionGateway(gateway).nonce(); - assertEq(prevNonce, 0); - - // Request - vm.prank(sender); - bytes32 requestId = TestConsumer(payable(address(consumer))).sendRequest{value: DEFAULT_FEE}( - address(gateway), FUNCTION_ID, REQUEST, CALLBACK_SELECTOR, CALLBACK_CONTEXT - ); - - // Fulfill - vm.expectEmit(true, true, true, true, gateway); - emit ProofFulfilled(requestId, REQUEST_OUTPUT_HASH, REQUEST_PROOF); - FunctionGateway(gateway).fulfill(requestId, REQUEST_OUTPUT_HASH, REQUEST_PROOF); - - ( - bytes32 functionId, - bytes32 inputHash, - bytes32 outputHash, - bytes32 contextHash, - address callbackAddress, - bytes4 callbackSelector, - bool proofFulfilled, - bool callbackFulfilled - ) = FunctionGateway(gateway).requests(requestId); - assertEq(prevNonce + 1, FunctionGateway(gateway).nonce()); - assertEq(FUNCTION_ID, functionId); - assertEq(sha256(REQUEST), inputHash); - assertEq(REQUEST_OUTPUT_HASH, outputHash); - assertEq(keccak256(CALLBACK_CONTEXT), contextHash); - assertEq(address(consumer), callbackAddress); - assertEq(CALLBACK_SELECTOR, callbackSelector); - assertEq(true, proofFulfilled); - assertEq(false, callbackFulfilled); - } - - function test_Callback_WhenFromContract() public { - uint256 prevNonce = FunctionGateway(gateway).nonce(); - assertEq(prevNonce, 0); - - // Request - vm.prank(sender); - bytes32 requestId = TestConsumer(payable(address(consumer))).sendRequest{value: DEFAULT_FEE}( - address(gateway), FUNCTION_ID, REQUEST, CALLBACK_SELECTOR, CALLBACK_CONTEXT - ); - - // Fulfill - FunctionGateway(gateway).fulfill(requestId, REQUEST_OUTPUT_HASH, REQUEST_PROOF); - - // Callback - vm.expectEmit(true, true, true, true, gateway); - emit CallbackFulfilled(requestId, REQUEST_OUTPUT, CALLBACK_CONTEXT); - FunctionGateway(gateway).callback(requestId, REQUEST_OUTPUT, CALLBACK_CONTEXT); - ( - bytes32 functionId, - bytes32 inputHash, - bytes32 outputHash, - bytes32 contextHash, - address callbackAddress, - bytes4 callbackSelector, - bool proofFulfilled, - bool callbackFulfilled - ) = FunctionGateway(gateway).requests(requestId); - assertEq(prevNonce + 1, FunctionGateway(gateway).nonce()); - assertEq(FUNCTION_ID, functionId); - assertEq(sha256(REQUEST), inputHash); - assertEq(REQUEST_OUTPUT_HASH, outputHash); - assertEq(keccak256(CALLBACK_CONTEXT), contextHash); - assertEq(address(consumer), callbackAddress); - assertEq(CALLBACK_SELECTOR, callbackSelector); - assertEq(true, proofFulfilled); - assertEq(true, callbackFulfilled); - } - - function test_RevertCallback_WhenReentered() public { - uint256 prevNonce = FunctionGateway(gateway).nonce(); - assertEq(prevNonce, 0); - - // Setup attack consumer - consumer = payable(address(new AttackConsumer())); - - // Request - vm.prank(sender); - bytes32 requestId = TestConsumer(payable(address(consumer))).sendRequest( - address(gateway), FUNCTION_ID, REQUEST, CALLBACK_SELECTOR, CALLBACK_CONTEXT - ); - - AttackConsumer(consumer).setCallbackParams(requestId, REQUEST_OUTPUT, CALLBACK_CONTEXT); - - // Fulfill - FunctionGateway(gateway).fulfill(requestId, REQUEST_OUTPUT_HASH, REQUEST_PROOF); - - // Callback - // inner error: vm.expectRevert(abi.encodeWithSelector(CallbackAlreadyFulfilled.selector, requestId)); - vm.expectRevert( - abi.encodeWithSelector(CallbackFailed.selector, consumer, AttackConsumer.handleRequest.selector) - ); - FunctionGateway(gateway).callback(requestId, REQUEST_OUTPUT, CALLBACK_CONTEXT); - } -} diff --git a/contracts/test/NounsOwnership.t.sol b/contracts/test/NounsOwnership.t.sol deleted file mode 100644 index 2c730609f..000000000 --- a/contracts/test/NounsOwnership.t.sol +++ /dev/null @@ -1,150 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -import "forge-std/Vm.sol"; -import "forge-std/console.sol"; -import "forge-std/Test.sol"; - -import {StorageOracle} from "../src/examples/storage/StorageOracle.sol"; -import {NounsOwnership} from "../src/examples/storage/NounsOwnership.sol"; -import {FunctionGateway} from "../src/FunctionGateway.sol"; - -import {IFunctionGatewayEvents, IFunctionGatewayErrors} from "../src/interfaces/IFunctionGateway.sol"; -import {MockFunctionGateway} from "../src/mocks/MockFunctionGateway.sol"; -import {Proxy} from "src/upgrades/Proxy.sol"; - -contract TestError is IFunctionGatewayErrors { - error InvalidL1BlockHash(); - error InvalidL1BlockNumber(); - error NotFromFunctionGateway(address sender); - error OutdatedBlockNumber(uint256 blockNumber, uint256 storedBlockNumber); -} - -contract TestEvents is IFunctionGatewayEvents { - event SlotRequested(uint256 indexed blockNumber, bytes32 indexed blockHash, address indexed account, uint256 slot); - event SlotUpdated(uint256 indexed blockNumber, address indexed account, uint256 slot, bytes32 value); -} - -contract NounsOwnershipTest is Test, TestError, TestEvents { - /// @dev Fork a specific block so that L1_Block.hash() returns a consistent value, and thus, proof input is the same. - uint256 internal constant BLOCK_NUMBER = 12345678; - /// @dev Nouns NFT contract: https://etherscan.io/address/0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03 - address internal constant NOUNS_ACCOUNT = 0x9C8fF314C9Bc7F6e59A9d9225Fb22946427eDC03; - /// @dev Get slot key for noun40.eth's (0xa555d1Ee16780B2d414eD97f4f169c0740099615) NFT - // 1. `mapping(uint256 => address) private _owners` slot is #3 - // 2. tokenId is to check 40 - uint256 internal constant OWNERS_SLOT = 3; - uint256 internal constant NOUN_NUMBER = 40; - address internal constant NOUN_OWNER = 0xa555d1Ee16780B2d414eD97f4f169c0740099615; - uint256 internal constant SLOT = uint256(keccak256(abi.encode(NOUN_NUMBER, OWNERS_SLOT))); - bytes32 internal constant FUNCTION_ID = keccak256("STORAGE"); - - address internal timelock; - address internal guardian; - address internal gateway; - address internal storageOracle; - address internal nounsOwnership; - - bool internal skipTest; - - modifier onlyWithFork() { - if (skipTest) return; - _; - } - - function setUp() public { - try vm.envString("RPC_420") returns (string memory RPC_420) { - vm.createSelectFork(RPC_420, BLOCK_NUMBER); - } catch { - console.log("RPC_420 not set, skipping test"); - skipTest = true; - } - - timelock = makeAddr("timelock"); - guardian = makeAddr("guardian"); - gateway = address(new MockFunctionGateway()); - - // Deploy StorageOracle - address storageOracleImpl = address(new StorageOracle()); - storageOracle = address(new Proxy(storageOracleImpl, "")); - StorageOracle(storageOracle).initialize(address(gateway), FUNCTION_ID, timelock, guardian); - - nounsOwnership = address(new NounsOwnership(storageOracle)); - } - - function test_ClaimOwnership() public onlyWithFork { - bytes32 requestId = NounsOwnership(nounsOwnership).claimOwnership(NOUN_NUMBER); - - (bytes32 functionId,,,, address callbackAddress,, bool proofFulfilled, bool callbackFulfilled) = - FunctionGateway(gateway).requests(requestId); - assertEq(FUNCTION_ID, functionId); - assertEq(storageOracle, callbackAddress); - assertEq(false, proofFulfilled); - assertEq(false, callbackFulfilled); - } - - function test_OwnerOf() public onlyWithFork { - bytes32 requestId = NounsOwnership(nounsOwnership).claimOwnership(NOUN_NUMBER); - - bytes memory output = abi.encode(NOUN_OWNER); - bytes memory context = abi.encode(BLOCK_NUMBER, NOUNS_ACCOUNT, SLOT); - MockFunctionGateway(gateway).callback(requestId, output, context); - - address owner = NounsOwnership(nounsOwnership).ownerOf(NOUN_NUMBER); - assertEq(NOUN_OWNER, owner); - } - - function test_LastUpdateBlock() public onlyWithFork { - bytes32 requestId = NounsOwnership(nounsOwnership).claimOwnership(NOUN_NUMBER); - - bytes memory output = abi.encode(NOUN_OWNER); - bytes memory context = abi.encode(BLOCK_NUMBER, NOUNS_ACCOUNT, SLOT); - MockFunctionGateway(gateway).callback(requestId, output, context); - - uint256 blockNumber = NounsOwnership(nounsOwnership).lastUpdatedBlock(NOUN_NUMBER); - assertEq(BLOCK_NUMBER, blockNumber); - } - - function test_OwnerOf_WithFixture() public onlyWithFork { - bytes memory context = abi.encode(BLOCK_NUMBER, NOUNS_ACCOUNT, SLOT); - - // Use input and output from fixture - string memory root = vm.projectRoot(); - string memory path = string.concat(root, "/test/fixtures/nouns-fixture.json"); - MockFunctionGateway(gateway).loadFixture(path); - NounsOwnership(nounsOwnership).claimOwnership(NOUN_NUMBER); - - address owner = NounsOwnership(nounsOwnership).ownerOf(NOUN_NUMBER); - assertEq(NOUN_OWNER, owner); - } -} - -// Nouns NFT contract: https://etherscan.io/address/0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03 -// Storage Layout: -// | Name | Type | Slot | Offset | Bytes | Contract | -// |--------------------|-------------------------------------------------------------------------------|------|--------|-------|-------------------------------------| -// | _owner | address | 0 | 0 | 20 | contracts/NounsToken.sol:NounsToken | -// | _name | string | 1 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | _symbol | string | 2 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | _owners | mapping(uint256 => address) | 3 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | _balances | mapping(address => uint256) | 4 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | _tokenApprovals | mapping(uint256 => address) | 5 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | _operatorApprovals | mapping(address => mapping(address => bool)) | 6 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | _ownedTokens | mapping(address => mapping(uint256 => uint256)) | 7 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | _ownedTokensIndex | mapping(uint256 => uint256) | 8 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | _allTokens | uint256[] | 9 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | _allTokensIndex | mapping(uint256 => uint256) | 10 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | _delegates | mapping(address => address) | 11 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | checkpoints | mapping(address => mapping(uint32 => struct ERC721Checkpointable.Checkpoint)) | 12 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | numCheckpoints | mapping(address => uint32) | 13 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | nonces | mapping(address => uint256) | 14 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | noundersDAO | address | 15 | 0 | 20 | contracts/NounsToken.sol:NounsToken | -// | minter | address | 16 | 0 | 20 | contracts/NounsToken.sol:NounsToken | -// | descriptor | contract INounsDescriptorMinimal | 17 | 0 | 20 | contracts/NounsToken.sol:NounsToken | -// | seeder | contract INounsSeeder | 18 | 0 | 20 | contracts/NounsToken.sol:NounsToken | -// | isMinterLocked | bool | 18 | 20 | 1 | contracts/NounsToken.sol:NounsToken | -// | isDescriptorLocked | bool | 18 | 21 | 1 | contracts/NounsToken.sol:NounsToken | -// | isSeederLocked | bool | 18 | 22 | 1 | contracts/NounsToken.sol:NounsToken | -// | seeds | mapping(uint256 => struct INounsSeeder.Seed) | 19 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | _currentNounId | uint256 | 20 | 0 | 32 | contracts/NounsToken.sol:NounsToken | -// | _contractURIHash | string | 21 | 0 | 32 | contracts/NounsToken.sol:NounsToken | diff --git a/contracts/test/TestUtils.sol b/contracts/test/TestUtils.sol deleted file mode 100644 index ee9e5a223..000000000 --- a/contracts/test/TestUtils.sol +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -import {FunctionGateway} from "src/FunctionGateway.sol"; -import {IFunctionVerifier} from "src/interfaces/IFunctionVerifier.sol"; - -library TestFuncLib { - function request( - address _gateway, - bytes32 _functionId, - bytes memory _input, - bytes4 _callbackSelector, - bytes memory _context - ) internal returns (bytes32) { - return FunctionGateway(_gateway).request{value: msg.value}(_functionId, _input, _callbackSelector, _context); - } - - function decode(bytes memory _output) internal pure returns (bool) { - return abi.decode(_output, (bool)); - } -} - -contract TestConsumer { - uint256 public nonce; - - error NotVerified(); - error InvalidRequestNonce(uint256 expectedNonce, uint256 actualNonce); - - function sendRequest( - address _gateway, - bytes32 _functionId, - bytes memory _input, - bytes4 _callbackSelector, - bytes memory _context - ) external payable returns (bytes32) { - return TestFuncLib.request(_gateway, _functionId, _input, _callbackSelector, _context); - } - - function handleRequest(bytes memory _output, bytes memory _context) external { - bool verified = TestFuncLib.decode(_output); - if (!verified) { - revert NotVerified(); - } - - uint256 requestNonce = abi.decode(_context, (uint256)); - if (requestNonce != nonce) { - revert InvalidRequestNonce(nonce, requestNonce); - } - - ++nonce; - } - - receive() external payable {} -} - -// Attempts re-entry into the gateway contract. -contract AttackConsumer { - uint256 public nonce; - - bytes32 public requestId; - bytes public output; - bytes public context; - - error NotVerified(); - error InvalidRequestNonce(uint256 expectedNonce, uint256 actualNonce); - - function sendRequest( - address _gateway, - bytes32 _functionId, - bytes memory _input, - bytes4 _callbackSelector, - bytes memory _context - ) external payable returns (bytes32) { - return TestFuncLib.request(_gateway, _functionId, _input, _callbackSelector, _context); - } - - function setCallbackParams(bytes32 _requestId, bytes memory _output, bytes memory _proof) external { - requestId = _requestId; - output = _output; - context = _proof; - } - - function handleRequest(bytes memory, bytes memory) external { - FunctionGateway(msg.sender).callback(requestId, output, context); - } - - receive() external payable {} -} - -contract TestFunctionVerifier is IFunctionVerifier { - function verificationKeyHash() external pure returns (bytes32) { - return keccak256("verificationKeyHash"); - } - - function verify(bytes32, bytes32, bytes memory) external pure returns (bool) { - return true; - } -} diff --git a/contracts/test/fixtures/nouns-fixture.json b/contracts/test/fixtures/nouns-fixture.json deleted file mode 100644 index d596de1c9..000000000 --- a/contracts/test/fixtures/nouns-fixture.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "input": "0xb99c7a251e3880d3560ff23412f4b880c196c252a791a4667694447892c051a70000000000000000000000009c8ff314c9bc7f6e59a9d9225fb22946427edc03f787d5ff306ee7ea1d7b35b5cacd5a837646921c113945dbc3a3b6329ce40033", - "output": "0x000000000000000000000000a555d1Ee16780B2d414eD97f4f169c0740099615" -} \ No newline at end of file From 7e2ab7f6df6f2c14697b47f6063ecb5783e6ae16 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Tue, 10 Oct 2023 17:50:56 -0700 Subject: [PATCH 13/19] feat: cleanup --- contracts/src/FunctionGateway.sol | 33 +++++-------------- contracts/src/interfaces/IFunctionGateway.sol | 9 +---- contracts/test/libraries/OutputReader.t.sol | 2 +- 3 files changed, 10 insertions(+), 34 deletions(-) diff --git a/contracts/src/FunctionGateway.sol b/contracts/src/FunctionGateway.sol index d0b98c16f..7cb00ae55 100644 --- a/contracts/src/FunctionGateway.sol +++ b/contracts/src/FunctionGateway.sol @@ -6,14 +6,15 @@ import {IFunctionGateway} from "./interfaces/IFunctionGateway.sol"; import {IFunctionVerifier} from "./interfaces/IFunctionVerifier.sol"; import {FunctionRegistry} from "./FunctionRegistry.sol"; import {TimelockedUpgradeable} from "./upgrades/TimelockedUpgradeable.sol"; +import {IFeeVault} from "./payments/interfaces/IFeeVault.sol"; contract FunctionGateway is IFunctionGateway, FunctionRegistry, TimelockedUpgradeable { - /// @dev The default gas limit for requests. - uint32 public constant DEFAULT_GAS_LIMIT = 1000000; + /// @dev The address of the fee vault. + address public feeVault; /// @dev A nonce for keeping track of requests. uint32 public nonce; @@ -40,28 +41,6 @@ contract FunctionGateway is __TimelockedUpgradeable_init(_timelock, _guardian); } - /// @dev Creates a onchain request for a proof. The output and proof is fulfilled asynchronously - /// by the provided callback. - /// @param _functionId The function identifier. - /// @param _input The function input. - /// @param _context The function context. - /// @param _callbackSelector The selector of the callback function. - function zkRequest( - bytes32 _functionId, - bytes memory _input, - bytes memory _context, - bytes4 _callbackSelector - ) external returns (bytes32) { - return - zkRequest( - _functionId, - _input, - _context, - _callbackSelector, - DEFAULT_GAS_LIMIT - ); - } - /// @dev Creates a onchain request for a proof. The output and proof is fulfilled asynchronously /// by the provided callback. /// @param _functionId The function identifier. @@ -75,7 +54,7 @@ contract FunctionGateway is bytes memory _context, bytes4 _callbackSelector, uint32 _callbackGasLimit - ) public returns (bytes32) { + ) external payable returns (bytes32) { // Compute the callback hash uniquely associated with this request. bytes32 inputHash = sha256(_input); bytes32 contextHash = sha256(_context); @@ -103,6 +82,10 @@ contract FunctionGateway is // Increment the nonce. nonce++; + + // Send the fee to the vault. + IFeeVault(feeVault).depositNative{value: msg.value}(callbackAddress); + return requestHash; } diff --git a/contracts/src/interfaces/IFunctionGateway.sol b/contracts/src/interfaces/IFunctionGateway.sol index 2a8813f57..1158f3c6f 100644 --- a/contracts/src/interfaces/IFunctionGateway.sol +++ b/contracts/src/interfaces/IFunctionGateway.sol @@ -41,20 +41,13 @@ interface IFunctionGatewayErrors { } interface IFunctionGateway is IFunctionGatewayEvents, IFunctionGatewayErrors { - function zkRequest( - bytes32 _functionId, - bytes memory _input, - bytes memory _context, - bytes4 _callbackSelector - ) external returns (bytes32); - function zkRequest( bytes32 _functionId, bytes memory _input, bytes memory _context, bytes4 _callbackSelector, uint32 _callbackGasLimit - ) external returns (bytes32); + ) external payable returns (bytes32); function zkCall( bytes32 _functionId, diff --git a/contracts/test/libraries/OutputReader.t.sol b/contracts/test/libraries/OutputReader.t.sol index ffe328fa8..d784588bd 100644 --- a/contracts/test/libraries/OutputReader.t.sol +++ b/contracts/test/libraries/OutputReader.t.sol @@ -5,7 +5,7 @@ import "forge-std/Vm.sol"; import "forge-std/console.sol"; import "forge-std/Test.sol"; -import {OutputReader} from "src/libraries/OutputReader.sol"; +import {OutputReader} from "../../src/libraries/OutputReader.sol"; contract OutputReaderTest is Test { function setUp() public {} From e518116378e18fd0ef1cbfbdf4fe5015263967e8 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Tue, 10 Oct 2023 18:09:28 -0700 Subject: [PATCH 14/19] feat: cleanup --- contracts/src/FunctionGateway.sol | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/contracts/src/FunctionGateway.sol b/contracts/src/FunctionGateway.sol index 7cb00ae55..8e28145b1 100644 --- a/contracts/src/FunctionGateway.sol +++ b/contracts/src/FunctionGateway.sol @@ -31,6 +31,9 @@ contract FunctionGateway is /// @dev The currently verified function output. bytes public verifiedOutput; + /// @dev A flag that indicates whether the contract is currently making a callback. + bool public isCallback; + /// @dev Initializes the contract. /// @param _timelock The address of the timelock contract. /// @param _guardian The address of the guardian. @@ -38,6 +41,7 @@ contract FunctionGateway is address _timelock, address _guardian ) external initializer { + isCallback = false; __TimelockedUpgradeable_init(_timelock, _guardian); } @@ -134,9 +138,11 @@ contract FunctionGateway is _verify(_functionId, _inputHash, outputHash, _proof); // Execute the callback. + isCallback = true; (bool status, ) = _callbackAddress.call( abi.encodeWithSelector(_callbackSelector, _output, _context) ); + isCallback = false; // If the callback failed, revert. if (!status) { From 51a8be063cd23e55c94faef86562a0ff66348854 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Tue, 10 Oct 2023 19:56:02 -0700 Subject: [PATCH 15/19] feat: add contracts ci if contracts folder changes --- contracts/src/FunctionGateway.sol | 50 +++++++++++++------ contracts/src/interfaces/IFunctionGateway.sol | 4 +- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/contracts/src/FunctionGateway.sol b/contracts/src/FunctionGateway.sol index 8e28145b1..4c4158adb 100644 --- a/contracts/src/FunctionGateway.sol +++ b/contracts/src/FunctionGateway.sol @@ -52,7 +52,7 @@ contract FunctionGateway is /// @param _context The function context. /// @param _callbackSelector The selector of the callback function. /// @param _callbackGasLimit The gas limit for the callback function. - function zkRequest( + function requestCallback( bytes32 _functionId, bytes memory _input, bytes memory _context, @@ -61,7 +61,7 @@ contract FunctionGateway is ) external payable returns (bytes32) { // Compute the callback hash uniquely associated with this request. bytes32 inputHash = sha256(_input); - bytes32 contextHash = sha256(_context); + bytes32 contextHash = keccak256(_context); address callbackAddress = msg.sender; bytes32 requestHash = _requestHash( nonce, @@ -73,6 +73,9 @@ contract FunctionGateway is _callbackGasLimit ); + // Increment the nonce. + nonce++; + // Store the callback hash. requests[nonce] = requestHash; emit Request( @@ -84,9 +87,6 @@ contract FunctionGateway is _callbackGasLimit ); - // Increment the nonce. - nonce++; - // Send the fee to the vault. IFeeVault(feeVault).depositNative{value: msg.value}(callbackAddress); @@ -103,7 +103,7 @@ contract FunctionGateway is /// @param _context The function context. /// @param _output The function output. /// @param _proof The function proof. - function zkRequestFulfill( + function fulfillCallback( uint32 _nonce, bytes32 _functionId, bytes32 _inputHash, @@ -115,7 +115,7 @@ contract FunctionGateway is bytes memory _proof ) external { // Reconstruct the callback hash. - bytes32 contextHash = sha256(_context); + bytes32 contextHash = keccak256(_context); bytes32 requestHash = _requestHash( _nonce, _functionId, @@ -131,6 +131,9 @@ contract FunctionGateway is revert InvalidRequest(_nonce, requests[_nonce], requestHash); } + // Delete the callback hash for a gas refund. + delete requests[_nonce]; + // Compute the output hash. bytes32 outputHash = sha256(_output); @@ -149,28 +152,45 @@ contract FunctionGateway is revert CallbackFailed(_callbackSelector, _output, _context); } - // Delete the callback hash for a gas refund. - delete requests[_nonce]; - // Emit event. emit RequestFulfilled(_nonce, _functionId, _inputHash, outputHash); } + // function requestCall(bytes32 _functionId, bytes memory _input) external payable { + // emit Request( + // -1, + // _functionId, + // _input, + // "", + // bytes4(0), + // 0 + // ); + // } + /// @dev If the call matches the currently verified function, returns the output. Otherwise, /// this function reverts. /// @param _functionId The function identifier. /// @param _input The function input. - function zkCall( + function verifyCall( bytes32 _functionId, bytes memory _input - ) external view returns (bytes memory) { + ) external view returns (bool, bytes memory) { bytes32 inputHash = sha256(_input); if ( verifiedFunctionId == _functionId && verifiedInputHash == inputHash ) { - return verifiedOutput; + return (true, verifiedOutput); + } else { + emit Request( + 4294967295, + _functionId, + _input, + "", + , + _callbackGasLimit + ); + return (false, ""); } - revert InvalidCall(_functionId, inputHash); } /// @dev The entrypoint for fulfilling a call. @@ -180,7 +200,7 @@ contract FunctionGateway is /// @param _proof The function proof. /// @param _callbackAddress The address of the callback contract. /// @param _callbackData The data for the callback function. - function zkCallFulfill( + function fulfillCall( bytes32 _functionId, bytes memory _input, bytes memory _output, diff --git a/contracts/src/interfaces/IFunctionGateway.sol b/contracts/src/interfaces/IFunctionGateway.sol index 1158f3c6f..3d0e055c6 100644 --- a/contracts/src/interfaces/IFunctionGateway.sol +++ b/contracts/src/interfaces/IFunctionGateway.sol @@ -30,7 +30,7 @@ interface IFunctionGatewayErrors { bytes32 requestHash ); error CallbackFailed(bytes4 callbackSelector, bytes output, bytes context); - error InvalidCall(bytes32 functionId, bytes32 inputHash); + error InvalidCall(bytes32 functionId, bytes input); error CallFailed(address callbackAddress, bytes callbackData); error InvalidProof( address verifier, @@ -52,5 +52,5 @@ interface IFunctionGateway is IFunctionGatewayEvents, IFunctionGatewayErrors { function zkCall( bytes32 _functionId, bytes memory _input - ) external view returns (bytes memory); + ) external view returns (bool, bytes memory); } From a8cf66ffe63a0927e391fdf430dc2758419c8add Mon Sep 17 00:00:00 2001 From: John Guibas Date: Tue, 10 Oct 2023 20:22:28 -0700 Subject: [PATCH 16/19] feat: add contracts ci if contracts folder changes --- contracts/src/FunctionGateway.sol | 81 ++++++++++--------- contracts/src/interfaces/IFunctionGateway.sol | 21 ++++- 2 files changed, 60 insertions(+), 42 deletions(-) diff --git a/contracts/src/FunctionGateway.sol b/contracts/src/FunctionGateway.sol index 4c4158adb..c07725481 100644 --- a/contracts/src/FunctionGateway.sol +++ b/contracts/src/FunctionGateway.sol @@ -78,7 +78,7 @@ contract FunctionGateway is // Store the callback hash. requests[nonce] = requestHash; - emit Request( + emit RequestCallback( nonce, _functionId, _input, @@ -93,6 +93,48 @@ contract FunctionGateway is return requestHash; } + /// @dev Creates a proof request for a call. This function is equivalent to an off-chain + /// request. + /// @param _functionId The function identifier. + /// @param _input The function input. + /// @param _callbackAddress The address of the callback contract. + /// @param _callbackData The data for the callback function. + function requestCall( + bytes32 _functionId, + bytes memory _input, + address _callbackAddress, + bytes memory _callbackData + ) external payable { + // Emit event. + emit RequestCall( + _functionId, + _input, + _callbackAddress, + _callbackData + ); + + // Send the fee to the vault. + IFeeVault(feeVault).depositNative{value: msg.value}(_callbackAddress); + } + + /// @dev If the call matches the currently verified function, returns the output. Otherwise, + /// this function reverts. + /// @param _functionId The function identifier. + /// @param _input The function input. + function verifyCall( + bytes32 _functionId, + bytes memory _input + ) external view returns (bytes memory) { + bytes32 inputHash = sha256(_input); + if ( + verifiedFunctionId == _functionId && verifiedInputHash == inputHash + ) { + return verifiedOutput; + } else { + revert InvalidCall(_functionId, _input); + } + } + /// @dev Fulfills a request by providing the output and proof. /// @param _nonce The nonce of the request. /// @param _functionId The function identifier. @@ -156,43 +198,6 @@ contract FunctionGateway is emit RequestFulfilled(_nonce, _functionId, _inputHash, outputHash); } - // function requestCall(bytes32 _functionId, bytes memory _input) external payable { - // emit Request( - // -1, - // _functionId, - // _input, - // "", - // bytes4(0), - // 0 - // ); - // } - - /// @dev If the call matches the currently verified function, returns the output. Otherwise, - /// this function reverts. - /// @param _functionId The function identifier. - /// @param _input The function input. - function verifyCall( - bytes32 _functionId, - bytes memory _input - ) external view returns (bool, bytes memory) { - bytes32 inputHash = sha256(_input); - if ( - verifiedFunctionId == _functionId && verifiedInputHash == inputHash - ) { - return (true, verifiedOutput); - } else { - emit Request( - 4294967295, - _functionId, - _input, - "", - , - _callbackGasLimit - ); - return (false, ""); - } - } - /// @dev The entrypoint for fulfilling a call. /// @param _functionId The function identifier. /// @param _input The function input. diff --git a/contracts/src/interfaces/IFunctionGateway.sol b/contracts/src/interfaces/IFunctionGateway.sol index 3d0e055c6..ed8661283 100644 --- a/contracts/src/interfaces/IFunctionGateway.sol +++ b/contracts/src/interfaces/IFunctionGateway.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.0; interface IFunctionGatewayEvents { - event Request( + event RequestCallback( uint32 indexed nonce, bytes32 indexed functionId, bytes input, @@ -10,6 +10,12 @@ interface IFunctionGatewayEvents { bytes4 callbackSelector, uint32 callbackGasLimit ); + event RequestCall( + bytes32 indexed functionId, + bytes input, + address callbackAddress, + bytes callbackData + ); event RequestFulfilled( uint32 indexed nonce, bytes32 indexed functionId, @@ -41,7 +47,7 @@ interface IFunctionGatewayErrors { } interface IFunctionGateway is IFunctionGatewayEvents, IFunctionGatewayErrors { - function zkRequest( + function requestCallback( bytes32 _functionId, bytes memory _input, bytes memory _context, @@ -49,8 +55,15 @@ interface IFunctionGateway is IFunctionGatewayEvents, IFunctionGatewayErrors { uint32 _callbackGasLimit ) external payable returns (bytes32); - function zkCall( + function requestCall( + bytes32 _functionId, + bytes memory _input, + address _callbackAddress, + bytes memory _callbackData + ) external payable; + + function verifyCall( bytes32 _functionId, bytes memory _input - ) external view returns (bool, bytes memory); + ) external view returns (bytes memory); } From fef13c1af4e09974e9de6b7bc5e9a8173fff421f Mon Sep 17 00:00:00 2001 From: John Guibas Date: Tue, 10 Oct 2023 20:43:10 -0700 Subject: [PATCH 17/19] feat: add contracts ci if contracts folder changes --- contracts/src/FunctionGateway.sol | 21 ++++++++++--------- contracts/src/interfaces/IFunctionGateway.sol | 3 ++- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/contracts/src/FunctionGateway.sol b/contracts/src/FunctionGateway.sol index c07725481..29e9305ea 100644 --- a/contracts/src/FunctionGateway.sol +++ b/contracts/src/FunctionGateway.sol @@ -83,6 +83,7 @@ contract FunctionGateway is _functionId, _input, _context, + callbackAddress, _callbackSelector, _callbackGasLimit ); @@ -93,35 +94,35 @@ contract FunctionGateway is return requestHash; } - /// @dev Creates a proof request for a call. This function is equivalent to an off-chain - /// request. + /// @dev Creates a proof request for a call. This function is equivalent to an off-chain request + /// through an API. /// @param _functionId The function identifier. /// @param _input The function input. - /// @param _callbackAddress The address of the callback contract. - /// @param _callbackData The data for the callback function. + /// @param _address The address of the callback contract. + /// @param _data The data for the callback function. function requestCall( bytes32 _functionId, bytes memory _input, - address _callbackAddress, - bytes memory _callbackData + address _address, + bytes memory _data ) external payable { // Emit event. emit RequestCall( _functionId, _input, - _callbackAddress, - _callbackData + _address, + _data ); // Send the fee to the vault. - IFeeVault(feeVault).depositNative{value: msg.value}(_callbackAddress); + IFeeVault(feeVault).depositNative{value: msg.value}(_address); } /// @dev If the call matches the currently verified function, returns the output. Otherwise, /// this function reverts. /// @param _functionId The function identifier. /// @param _input The function input. - function verifyCall( + function verifiedCall( bytes32 _functionId, bytes memory _input ) external view returns (bytes memory) { diff --git a/contracts/src/interfaces/IFunctionGateway.sol b/contracts/src/interfaces/IFunctionGateway.sol index ed8661283..58c1a78f0 100644 --- a/contracts/src/interfaces/IFunctionGateway.sol +++ b/contracts/src/interfaces/IFunctionGateway.sol @@ -7,6 +7,7 @@ interface IFunctionGatewayEvents { bytes32 indexed functionId, bytes input, bytes context, + address callbackAddress, bytes4 callbackSelector, uint32 callbackGasLimit ); @@ -62,7 +63,7 @@ interface IFunctionGateway is IFunctionGatewayEvents, IFunctionGatewayErrors { bytes memory _callbackData ) external payable; - function verifyCall( + function verifiedCall( bytes32 _functionId, bytes memory _input ) external view returns (bytes memory); From 0130b08a315faf338f6d620c86d712e1fbb681ad Mon Sep 17 00:00:00 2001 From: John Guibas Date: Tue, 10 Oct 2023 20:45:52 -0700 Subject: [PATCH 18/19] forge fmt --- contracts/script/deploy/FunctionGateway.s.sol | 19 +--- contracts/src/FunctionGateway.sol | 102 ++++-------------- contracts/src/FunctionRegistry.sol | 43 +++----- contracts/src/interfaces/IFunctionGateway.sol | 47 ++------ contracts/src/mocks/MockFunctionGateway.sol | 4 + .../src/upgrades/TimelockedUpgradeable.sol | 16 +-- contracts/test/FunctionGateway.t.sol | 8 ++ 7 files changed, 63 insertions(+), 176 deletions(-) create mode 100644 contracts/src/mocks/MockFunctionGateway.sol create mode 100644 contracts/test/FunctionGateway.t.sol diff --git a/contracts/script/deploy/FunctionGateway.s.sol b/contracts/script/deploy/FunctionGateway.s.sol index 8751474da..a1e52dded 100644 --- a/contracts/script/deploy/FunctionGateway.s.sol +++ b/contracts/script/deploy/FunctionGateway.s.sol @@ -9,10 +9,7 @@ import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; contract DeployFunctionGateway is BaseScript { function run() external broadcaster { - console.log( - "Deploying FunctionGateway contract on chain %s", - Strings.toString(block.chainid) - ); + console.log("Deploying FunctionGateway contract on chain %s", Strings.toString(block.chainid)); address TIMELOCK = envAddress("TIMELOCK", block.chainid); address GUARDIAN = envAddress("GUARDIAN", block.chainid); @@ -23,23 +20,15 @@ contract DeployFunctionGateway is BaseScript { FunctionGateway gatewayImpl = new FunctionGateway{salt: CREATE2_SALT}(); FunctionGateway gateway; if (!UPGRADE) { - gateway = FunctionGateway( - address(new Proxy{salt: CREATE2_SALT}(address(gatewayImpl), "")) - ); + gateway = FunctionGateway(address(new Proxy{salt: CREATE2_SALT}(address(gatewayImpl), ""))); gateway.initialize(TIMELOCK, GUARDIAN); } else { - gateway = FunctionGateway( - envAddress("FUNCTION_GATEWAY", block.chainid) - ); + gateway = FunctionGateway(envAddress("FUNCTION_GATEWAY", block.chainid)); gateway.upgradeTo(address(gatewayImpl)); } // Write address writeEnvAddress(DEPLOYMENT_FILE, "FUNCTION_GATEWAY", address(gateway)); - writeEnvAddress( - DEPLOYMENT_FILE, - "FUNCTION_GATEWAY_IMPL", - address(gatewayImpl) - ); + writeEnvAddress(DEPLOYMENT_FILE, "FUNCTION_GATEWAY_IMPL", address(gatewayImpl)); } } diff --git a/contracts/src/FunctionGateway.sol b/contracts/src/FunctionGateway.sol index 29e9305ea..d60c174a3 100644 --- a/contracts/src/FunctionGateway.sol +++ b/contracts/src/FunctionGateway.sol @@ -8,11 +8,7 @@ import {FunctionRegistry} from "./FunctionRegistry.sol"; import {TimelockedUpgradeable} from "./upgrades/TimelockedUpgradeable.sol"; import {IFeeVault} from "./payments/interfaces/IFeeVault.sol"; -contract FunctionGateway is - IFunctionGateway, - FunctionRegistry, - TimelockedUpgradeable -{ +contract FunctionGateway is IFunctionGateway, FunctionRegistry, TimelockedUpgradeable { /// @dev The address of the fee vault. address public feeVault; @@ -37,10 +33,7 @@ contract FunctionGateway is /// @dev Initializes the contract. /// @param _timelock The address of the timelock contract. /// @param _guardian The address of the guardian. - function initialize( - address _timelock, - address _guardian - ) external initializer { + function initialize(address _timelock, address _guardian) external initializer { isCallback = false; __TimelockedUpgradeable_init(_timelock, _guardian); } @@ -64,13 +57,7 @@ contract FunctionGateway is bytes32 contextHash = keccak256(_context); address callbackAddress = msg.sender; bytes32 requestHash = _requestHash( - nonce, - _functionId, - inputHash, - contextHash, - callbackAddress, - _callbackSelector, - _callbackGasLimit + nonce, _functionId, inputHash, contextHash, callbackAddress, _callbackSelector, _callbackGasLimit ); // Increment the nonce. @@ -79,13 +66,7 @@ contract FunctionGateway is // Store the callback hash. requests[nonce] = requestHash; emit RequestCallback( - nonce, - _functionId, - _input, - _context, - callbackAddress, - _callbackSelector, - _callbackGasLimit + nonce, _functionId, _input, _context, callbackAddress, _callbackSelector, _callbackGasLimit ); // Send the fee to the vault. @@ -100,19 +81,12 @@ contract FunctionGateway is /// @param _input The function input. /// @param _address The address of the callback contract. /// @param _data The data for the callback function. - function requestCall( - bytes32 _functionId, - bytes memory _input, - address _address, - bytes memory _data - ) external payable { + function requestCall(bytes32 _functionId, bytes memory _input, address _address, bytes memory _data) + external + payable + { // Emit event. - emit RequestCall( - _functionId, - _input, - _address, - _data - ); + emit RequestCall(_functionId, _input, _address, _data); // Send the fee to the vault. IFeeVault(feeVault).depositNative{value: msg.value}(_address); @@ -122,14 +96,9 @@ contract FunctionGateway is /// this function reverts. /// @param _functionId The function identifier. /// @param _input The function input. - function verifiedCall( - bytes32 _functionId, - bytes memory _input - ) external view returns (bytes memory) { + function verifiedCall(bytes32 _functionId, bytes memory _input) external view returns (bytes memory) { bytes32 inputHash = sha256(_input); - if ( - verifiedFunctionId == _functionId && verifiedInputHash == inputHash - ) { + if (verifiedFunctionId == _functionId && verifiedInputHash == inputHash) { return verifiedOutput; } else { revert InvalidCall(_functionId, _input); @@ -160,13 +129,7 @@ contract FunctionGateway is // Reconstruct the callback hash. bytes32 contextHash = keccak256(_context); bytes32 requestHash = _requestHash( - _nonce, - _functionId, - _inputHash, - contextHash, - _callbackAddress, - _callbackSelector, - _callbackGasLimit + _nonce, _functionId, _inputHash, contextHash, _callbackAddress, _callbackSelector, _callbackGasLimit ); // Assert that the callback hash is unfilfilled. @@ -185,9 +148,7 @@ contract FunctionGateway is // Execute the callback. isCallback = true; - (bool status, ) = _callbackAddress.call( - abi.encodeWithSelector(_callbackSelector, _output, _context) - ); + (bool status,) = _callbackAddress.call(abi.encodeWithSelector(_callbackSelector, _output, _context)); isCallback = false; // If the callback failed, revert. @@ -227,7 +188,7 @@ contract FunctionGateway is verifiedOutput = _output; // Execute the callback. - (bool status, ) = _callbackAddress.call(_callbackData); + (bool status,) = _callbackAddress.call(_callbackData); if (!status) { revert CallFailed(_callbackAddress, _callbackData); } @@ -257,18 +218,11 @@ contract FunctionGateway is bytes4 _callbackSelector, uint32 _callbackGasLimit ) internal pure returns (bytes32) { - return - keccak256( - abi.encodePacked( - _nonce, - _functionId, - _inputHash, - _contextHash, - _callbackAddress, - _callbackSelector, - _callbackGasLimit - ) - ); + return keccak256( + abi.encodePacked( + _nonce, _functionId, _inputHash, _contextHash, _callbackAddress, _callbackSelector, _callbackGasLimit + ) + ); } /// @dev Verifies a proof with respect to a function identifier, input hash, and output hash. @@ -276,22 +230,10 @@ contract FunctionGateway is /// @param _inputHash The hash of the function input. /// @param _outputHash The hash of the function output. /// @param _proof The function proof. - function _verify( - bytes32 _functionId, - bytes32 _inputHash, - bytes32 _outputHash, - bytes memory _proof - ) internal { + function _verify(bytes32 _functionId, bytes32 _inputHash, bytes32 _outputHash, bytes memory _proof) internal { address verifier = verifiers[_functionId]; - if ( - !IFunctionVerifier(verifier).verify(_inputHash, _outputHash, _proof) - ) { - revert InvalidProof( - address(verifier), - _inputHash, - _outputHash, - _proof - ); + if (!IFunctionVerifier(verifier).verify(_inputHash, _outputHash, _proof)) { + revert InvalidProof(address(verifier), _inputHash, _outputHash, _proof); } } diff --git a/contracts/src/FunctionRegistry.sol b/contracts/src/FunctionRegistry.sol index 73c5276f1..bb24d8a9f 100644 --- a/contracts/src/FunctionRegistry.sol +++ b/contracts/src/FunctionRegistry.sol @@ -13,10 +13,7 @@ contract FunctionRegistry is IFunctionRegistry { /// @notice Registers a function, using a pre-deployed verifier. /// @param _verifier The address of the verifier. /// @param _name The name of the function to be registered. - function registerFunction( - address _verifier, - string memory _name - ) external returns (bytes32 functionId) { + function registerFunction(address _verifier, string memory _name) external returns (bytes32 functionId) { functionId = getFunctionId(msg.sender, _name); if (address(verifiers[functionId]) != address(0)) { revert FunctionAlreadyRegistered(functionId); // should call update instead @@ -33,10 +30,10 @@ contract FunctionRegistry is IFunctionRegistry { /// @notice Registers a function, using CREATE2 to deploy the verifier. /// @param _bytecode The bytecode of the verifier. /// @param _name The name of the function to be registered. - function deployAndRegisterFunction( - bytes memory _bytecode, - string memory _name - ) external returns (bytes32 functionId, address verifier) { + function deployAndRegisterFunction(bytes memory _bytecode, string memory _name) + external + returns (bytes32 functionId, address verifier) + { functionId = getFunctionId(msg.sender, _name); if (address(verifiers[functionId]) != address(0)) { revert FunctionAlreadyRegistered(functionId); // should call update instead @@ -52,10 +49,7 @@ contract FunctionRegistry is IFunctionRegistry { /// @notice Updates the function, using a pre-deployed verifier. /// @param _verifier The address of the verifier. /// @param _name The name of the function to be updated. - function updateFunction( - address _verifier, - string memory _name - ) external returns (bytes32 functionId) { + function updateFunction(address _verifier, string memory _name) external returns (bytes32 functionId) { functionId = getFunctionId(msg.sender, _name); if (msg.sender != verifierOwners[functionId]) { revert NotFunctionOwner(msg.sender, verifierOwners[functionId]); @@ -71,10 +65,10 @@ contract FunctionRegistry is IFunctionRegistry { /// @notice Updates the function, using CREATE2 to deploy the new verifier. /// @param _bytecode The bytecode of the verifier. /// @param _name The name of the function to be updated. - function deployAndUpdateFunction( - bytes memory _bytecode, - string memory _name - ) external returns (bytes32 functionId, address verifier) { + function deployAndUpdateFunction(bytes memory _bytecode, string memory _name) + external + returns (bytes32 functionId, address verifier) + { functionId = getFunctionId(msg.sender, _name); if (msg.sender != verifierOwners[functionId]) { revert NotFunctionOwner(msg.sender, verifierOwners[functionId]); @@ -88,26 +82,15 @@ contract FunctionRegistry is IFunctionRegistry { /// @notice Returns the functionId for a given owner and function name. /// @param _owner The owner of the function (sender of registerFunction). /// @param _name The name of the function. - function getFunctionId( - address _owner, - string memory _name - ) public pure returns (bytes32 functionId) { + function getFunctionId(address _owner, string memory _name) public pure returns (bytes32 functionId) { functionId = keccak256(abi.encode(_owner, _name)); } - function _deploy( - bytes memory _bytecode, - bytes32 _salt - ) internal returns (address deployedAddr) { + function _deploy(bytes memory _bytecode, bytes32 _salt) internal returns (address deployedAddr) { if (_bytecode.length == 0) revert EmptyBytecode(); assembly { - deployedAddr := create2( - 0, - add(_bytecode, 32), - mload(_bytecode), - _salt - ) + deployedAddr := create2(0, add(_bytecode, 32), mload(_bytecode), _salt) } if (deployedAddr == address(0)) revert FailedDeploy(); diff --git a/contracts/src/interfaces/IFunctionGateway.sol b/contracts/src/interfaces/IFunctionGateway.sol index 58c1a78f0..7ca4c1b41 100644 --- a/contracts/src/interfaces/IFunctionGateway.sol +++ b/contracts/src/interfaces/IFunctionGateway.sol @@ -11,40 +11,17 @@ interface IFunctionGatewayEvents { bytes4 callbackSelector, uint32 callbackGasLimit ); - event RequestCall( - bytes32 indexed functionId, - bytes input, - address callbackAddress, - bytes callbackData - ); - event RequestFulfilled( - uint32 indexed nonce, - bytes32 indexed functionId, - bytes32 inputHash, - bytes32 outputHash - ); - event Call( - bytes32 indexed functionId, - bytes32 inputHash, - bytes32 outputHash - ); + event RequestCall(bytes32 indexed functionId, bytes input, address callbackAddress, bytes callbackData); + event RequestFulfilled(uint32 indexed nonce, bytes32 indexed functionId, bytes32 inputHash, bytes32 outputHash); + event Call(bytes32 indexed functionId, bytes32 inputHash, bytes32 outputHash); } interface IFunctionGatewayErrors { - error InvalidRequest( - uint32 nonce, - bytes32 expectedRequestHash, - bytes32 requestHash - ); + error InvalidRequest(uint32 nonce, bytes32 expectedRequestHash, bytes32 requestHash); error CallbackFailed(bytes4 callbackSelector, bytes output, bytes context); error InvalidCall(bytes32 functionId, bytes input); error CallFailed(address callbackAddress, bytes callbackData); - error InvalidProof( - address verifier, - bytes32 inputHash, - bytes32 outputHash, - bytes proof - ); + error InvalidProof(address verifier, bytes32 inputHash, bytes32 outputHash, bytes proof); } interface IFunctionGateway is IFunctionGatewayEvents, IFunctionGatewayErrors { @@ -56,15 +33,9 @@ interface IFunctionGateway is IFunctionGatewayEvents, IFunctionGatewayErrors { uint32 _callbackGasLimit ) external payable returns (bytes32); - function requestCall( - bytes32 _functionId, - bytes memory _input, - address _callbackAddress, - bytes memory _callbackData - ) external payable; + function requestCall(bytes32 _functionId, bytes memory _input, address _callbackAddress, bytes memory _callbackData) + external + payable; - function verifiedCall( - bytes32 _functionId, - bytes memory _input - ) external view returns (bytes memory); + function verifiedCall(bytes32 _functionId, bytes memory _input) external view returns (bytes memory); } diff --git a/contracts/src/mocks/MockFunctionGateway.sol b/contracts/src/mocks/MockFunctionGateway.sol new file mode 100644 index 000000000..90df14ff6 --- /dev/null +++ b/contracts/src/mocks/MockFunctionGateway.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; + +contract MockFunctionGateway {} diff --git a/contracts/src/upgrades/TimelockedUpgradeable.sol b/contracts/src/upgrades/TimelockedUpgradeable.sol index 594130a19..7d0386941 100644 --- a/contracts/src/upgrades/TimelockedUpgradeable.sol +++ b/contracts/src/upgrades/TimelockedUpgradeable.sol @@ -9,12 +9,7 @@ import {AccessControlUpgradeable} from "@openzeppelin-upgradeable/contracts/acce /// @title TimelockedUpgradeable /// @notice A base contract that has modifiers to specify that certain functions are only callable /// by a sender with a timelock or guardian role. -abstract contract TimelockedUpgradeable is - Versioned, - Initializable, - UUPSUpgradeable, - AccessControlUpgradeable -{ +abstract contract TimelockedUpgradeable is Versioned, Initializable, UUPSUpgradeable, AccessControlUpgradeable { /// @notice A random constant used to identify addresses with the permission of a 'timelock'. /// @dev Should be set to a 'timelock' contract, which may only execute calls after being /// for a certain amount of time. @@ -48,10 +43,7 @@ abstract contract TimelockedUpgradeable is /// @notice Initializes the contract. /// @dev The DEFAULT_ADMIN_ROLE needs to be set but should be unused. - function __TimelockedUpgradeable_init( - address _timelock, - address _guardian - ) internal onlyInitializing { + function __TimelockedUpgradeable_init(address _timelock, address _guardian) internal onlyInitializing { __AccessControl_init(); __UUPSUpgradeable_init(); _grantRole(DEFAULT_ADMIN_ROLE, _timelock); @@ -60,7 +52,5 @@ abstract contract TimelockedUpgradeable is } /// @notice Authorizes an upgrade for the implementation contract. - function _authorizeUpgrade( - address newImplementation - ) internal virtual override onlyTimelock {} + function _authorizeUpgrade(address newImplementation) internal virtual override onlyTimelock {} } diff --git a/contracts/test/FunctionGateway.t.sol b/contracts/test/FunctionGateway.t.sol new file mode 100644 index 000000000..471551cf3 --- /dev/null +++ b/contracts/test/FunctionGateway.t.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; + +import "forge-std/Vm.sol"; +import "forge-std/console.sol"; +import "forge-std/Test.sol"; + +contract FunctionGatewayTest is Test {} From 3698ada4e7416c0d6f4ef8f56875ff9f310e2ef7 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Wed, 11 Oct 2023 18:56:00 -0700 Subject: [PATCH 19/19] formatting --- contracts/foundry.toml | 7 ++ contracts/script/deploy/FunctionGateway.s.sol | 7 +- contracts/script/deploy/Guardian.s.sol | 12 ++- .../script/deploy/SuccinctFeeVault.s.sol | 4 +- contracts/script/misc/Base.s.sol | 20 +++-- contracts/script/misc/Upgrade.s.sol | 83 ++++++++++++++----- contracts/src/FunctionGateway.sol | 58 ++++++++++--- contracts/src/FunctionRegistry.sol | 21 ++++- contracts/src/interfaces/IFunctionGateway.sol | 22 +++-- .../src/interfaces/IFunctionRegistry.sol | 21 +++-- .../src/interfaces/IFunctionVerifier.sol | 4 +- contracts/src/libraries/OutputReader.sol | 24 +++++- contracts/src/upgrades/Timelock.sol | 9 +- .../src/upgrades/TimelockedUpgradeable.sol | 15 +++- 14 files changed, 239 insertions(+), 68 deletions(-) diff --git a/contracts/foundry.toml b/contracts/foundry.toml index a2d58d9c9..d3d6201eb 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -4,4 +4,11 @@ out = "out" libs = ["lib"] fs_permissions = [{ access = "read-write", path = "./"}] +# https://book.getfoundry.sh/reference/config/formatter#line_length +[fmt] +line_length = 100 +tab_width = 4 +func_attrs_with_params_multiline = true +ignore = ["lib/**"] + # See more config options https://github.com/foundry-rs/foundry/tree/master/config \ No newline at end of file diff --git a/contracts/script/deploy/FunctionGateway.s.sol b/contracts/script/deploy/FunctionGateway.s.sol index a1e52dded..542f74853 100644 --- a/contracts/script/deploy/FunctionGateway.s.sol +++ b/contracts/script/deploy/FunctionGateway.s.sol @@ -9,7 +9,9 @@ import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; contract DeployFunctionGateway is BaseScript { function run() external broadcaster { - console.log("Deploying FunctionGateway contract on chain %s", Strings.toString(block.chainid)); + console.log( + "Deploying FunctionGateway contract on chain %s", Strings.toString(block.chainid) + ); address TIMELOCK = envAddress("TIMELOCK", block.chainid); address GUARDIAN = envAddress("GUARDIAN", block.chainid); @@ -20,7 +22,8 @@ contract DeployFunctionGateway is BaseScript { FunctionGateway gatewayImpl = new FunctionGateway{salt: CREATE2_SALT}(); FunctionGateway gateway; if (!UPGRADE) { - gateway = FunctionGateway(address(new Proxy{salt: CREATE2_SALT}(address(gatewayImpl), ""))); + gateway = + FunctionGateway(address(new Proxy{salt: CREATE2_SALT}(address(gatewayImpl), ""))); gateway.initialize(TIMELOCK, GUARDIAN); } else { gateway = FunctionGateway(envAddress("FUNCTION_GATEWAY", block.chainid)); diff --git a/contracts/script/deploy/Guardian.s.sol b/contracts/script/deploy/Guardian.s.sol index 749d7f305..916bc34bf 100644 --- a/contracts/script/deploy/Guardian.s.sol +++ b/contracts/script/deploy/Guardian.s.sol @@ -10,7 +10,9 @@ import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; // "Guardian" refers to a Gnosis Safe proxy. contract DeployGuardian is BaseScript { function run() external broadcaster { - console.log("Deploying Guardian (Safe) contract on chain %s", Strings.toString(block.chainid)); + console.log( + "Deploying Guardian (Safe) contract on chain %s", Strings.toString(block.chainid) + ); // Check inputs @@ -48,6 +50,12 @@ contract DeployGuardian is BaseScript { address(0) ); - return Safe(payable(_safeFactory.createProxyWithNonce(address(_safeSingleton), initializer, uint256(_salt)))); + return Safe( + payable( + _safeFactory.createProxyWithNonce( + address(_safeSingleton), initializer, uint256(_salt) + ) + ) + ); } } diff --git a/contracts/script/deploy/SuccinctFeeVault.s.sol b/contracts/script/deploy/SuccinctFeeVault.s.sol index 37a175e30..f09657fd9 100644 --- a/contracts/script/deploy/SuccinctFeeVault.s.sol +++ b/contracts/script/deploy/SuccinctFeeVault.s.sol @@ -8,7 +8,9 @@ import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; contract DeploySuccinctFeeVault is BaseScript { function run() external broadcaster { - console.log("Deploying SuccinctFeeVault contract on chain %s", Strings.toString(block.chainid)); + console.log( + "Deploying SuccinctFeeVault contract on chain %s", Strings.toString(block.chainid) + ); // Check inputs bytes32 CREATE2_SALT = envBytes32("CREATE2_SALT"); diff --git a/contracts/script/misc/Base.s.sol b/contracts/script/misc/Base.s.sol index 89f6a4ecd..56f810144 100644 --- a/contracts/script/misc/Base.s.sol +++ b/contracts/script/misc/Base.s.sol @@ -76,7 +76,10 @@ abstract contract BaseScript is Script { return value; } - function envUint32s(string memory name, string memory delimiter) internal returns (uint32[] memory) { + function envUint32s(string memory name, string memory delimiter) + internal + returns (uint32[] memory) + { uint256[] memory values = new uint256[](0); values = vm.envOr(name, delimiter, values); if (values.length == 0) { @@ -167,9 +170,12 @@ abstract contract BaseScript is Script { console.log(string.concat(string.concat(addrVar, "="), Strings.toHexString(value))); } - function writeEnvAddresses(string memory file, string memory name, address[] memory values, string memory delimiter) - internal - { + function writeEnvAddresses( + string memory file, + string memory name, + address[] memory values, + string memory delimiter + ) internal { string memory addrVar = string.concat(name, "_", Strings.toString(block.chainid)); string memory line = string.concat(addrVar, "="); string memory addrs; @@ -243,7 +249,11 @@ abstract contract BaseScript is Script { return _b; } - function buildSignaturesFromArray(bytes[] memory _signatures) internal pure returns (bytes memory) { + function buildSignaturesFromArray(bytes[] memory _signatures) + internal + pure + returns (bytes memory) + { bytes memory signatures; for (uint256 i = 0; i < _signatures.length; i++) { signatures = bytes.concat(signatures, bytes(_signatures[i])); diff --git a/contracts/script/misc/Upgrade.s.sol b/contracts/script/misc/Upgrade.s.sol index 8d223127e..9ac4af967 100644 --- a/contracts/script/misc/Upgrade.s.sol +++ b/contracts/script/misc/Upgrade.s.sol @@ -15,7 +15,10 @@ import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; // ); // contract UpgradeSignSchedule is BaseScript { - function run(address PROXY, address IMPL) external returns (address signer, bytes memory signature) { + function run(address PROXY, address IMPL) + external + returns (address signer, bytes memory signature) + { // Check inputs address TIMELOCK = envAddress("TIMELOCK", block.chainid); address GUARDIAN = envAddress("GUARDIAN", block.chainid); @@ -36,9 +39,12 @@ contract UpgradeSignSchedule is BaseScript { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(IProxy.upgradeTo.selector, IMPL); - bytes32 id = ITimelock(TIMELOCK).hashOperationBatch(targets, values, payloads, 0, CREATE2_SALT); + bytes32 id = + ITimelock(TIMELOCK).hashOperationBatch(targets, values, payloads, 0, CREATE2_SALT); if (ITimelock(TIMELOCK).isOperation(id)) { - revert("operation already exists in Timelock, change CREATE2_SALT to schedule a new one"); + revert( + "operation already exists in Timelock, change CREATE2_SALT to schedule a new one" + ); } scheduleBatchData = abi.encodeWithSelector( @@ -82,7 +88,11 @@ contract UpgradeSignSchedule is BaseScript { // After enough signatures have been collected, a call to Safe.execTransaction(..., signatures) is // made which schedules the call on the Timelock. contract UpgradeSendSchedule is BaseScript { - function run(address PROXY, address IMPL, bytes memory _signatures) external broadcaster returns (bool success) { + function run(address PROXY, address IMPL, bytes memory _signatures) + external + broadcaster + returns (bool success) + { // Check inputs address TIMELOCK = envAddress("TIMELOCK", block.chainid); address GUARDIAN = envAddress("GUARDIAN", block.chainid); @@ -103,9 +113,12 @@ contract UpgradeSendSchedule is BaseScript { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(IProxy.upgradeTo.selector, IMPL); - bytes32 id = ITimelock(TIMELOCK).hashOperationBatch(targets, values, payloads, 0, CREATE2_SALT); + bytes32 id = + ITimelock(TIMELOCK).hashOperationBatch(targets, values, payloads, 0, CREATE2_SALT); if (ITimelock(TIMELOCK).isOperation(id)) { - revert("operation already exists in Timelock, change CREATE2_SALT to schedule a new one"); + revert( + "operation already exists in Timelock, change CREATE2_SALT to schedule a new one" + ); } scheduleBatchData = abi.encodeWithSelector( @@ -122,7 +135,9 @@ contract UpgradeSendSchedule is BaseScript { { if (ISafe(GUARDIAN).getThreshold() * 65 > _signatures.length) { console.log( - "not enough signatures, need %d have %d", ISafe(GUARDIAN).getThreshold(), _signatures.length / 65 + "not enough signatures, need %d have %d", + ISafe(GUARDIAN).getThreshold(), + _signatures.length / 65 ); return false; } @@ -147,7 +162,10 @@ contract UpgradeSendSchedule is BaseScript { // After MINIMUM_DELAY has passed, the call to Timelock.execute() can be made. contract UpgradeSignExecute is BaseScript { - function run(address PROXY, address IMPL) external returns (address signer, bytes memory signature) { + function run(address PROXY, address IMPL) + external + returns (address signer, bytes memory signature) + { // Check inputs address TIMELOCK = envAddress("TIMELOCK", block.chainid); address GUARDIAN = envAddress("GUARDIAN", block.chainid); @@ -168,7 +186,8 @@ contract UpgradeSignExecute is BaseScript { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(IProxy.upgradeTo.selector, IMPL); - bytes32 id = ITimelock(TIMELOCK).hashOperationBatch(targets, values, payloads, 0, CREATE2_SALT); + bytes32 id = + ITimelock(TIMELOCK).hashOperationBatch(targets, values, payloads, 0, CREATE2_SALT); if (ITimelock(TIMELOCK).isOperationDone(id)) { console.log("operation already executed in Timelock"); return (address(0), ""); @@ -212,7 +231,11 @@ contract UpgradeSignExecute is BaseScript { } contract UpgradeSendExecute is BaseScript { - function run(address PROXY, address IMPL, bytes memory _signatures) external broadcaster returns (bool success) { + function run(address PROXY, address IMPL, bytes memory _signatures) + external + broadcaster + returns (bool success) + { // Check inputs address TIMELOCK = envAddress("TIMELOCK", block.chainid); address GUARDIAN = envAddress("GUARDIAN", block.chainid); @@ -233,7 +256,8 @@ contract UpgradeSendExecute is BaseScript { bytes[] memory payloads = new bytes[](1); payloads[0] = abi.encodeWithSelector(IProxy.upgradeTo.selector, IMPL); - bytes32 id = ITimelock(TIMELOCK).hashOperationBatch(targets, values, payloads, 0, CREATE2_SALT); + bytes32 id = + ITimelock(TIMELOCK).hashOperationBatch(targets, values, payloads, 0, CREATE2_SALT); if (ITimelock(TIMELOCK).isOperationDone(id)) { console.log("operation already executed in Timelock"); return true; @@ -253,7 +277,9 @@ contract UpgradeSendExecute is BaseScript { { if (ISafe(GUARDIAN).getThreshold() * 65 > _signatures.length) { console.log( - "not enough signatures, need %d have %d", ISafe(GUARDIAN).getThreshold(), _signatures.length / 65 + "not enough signatures, need %d have %d", + ISafe(GUARDIAN).getThreshold(), + _signatures.length / 65 ); return false; } @@ -338,7 +364,11 @@ interface ISafe { event RemovedOwner(address owner); event SafeReceived(address indexed sender, uint256 value); event SafeSetup( - address indexed initiator, address[] owners, uint256 threshold, address initializer, address fallbackHandler + address indexed initiator, + address[] owners, + uint256 threshold, + address initializer, + address fallbackHandler ); event SignMsg(bytes32 indexed msgHash); @@ -347,10 +377,15 @@ interface ISafe { function approveHash(bytes32 hashToApprove) external; function approvedHashes(address, bytes32) external view returns (uint256); function changeThreshold(uint256 _threshold) external; - function checkNSignatures(bytes32 dataHash, bytes memory data, bytes memory signatures, uint256 requiredSignatures) + function checkNSignatures( + bytes32 dataHash, + bytes memory data, + bytes memory signatures, + uint256 requiredSignatures + ) external view; + function checkSignatures(bytes32 dataHash, bytes memory data, bytes memory signatures) external view; - function checkSignatures(bytes32 dataHash, bytes memory data, bytes memory signatures) external view; function disableModule(address prevModule, address module) external; function domainSeparator() external view returns (bytes32); function enableModule(address module) external; @@ -378,12 +413,18 @@ interface ISafe { address refundReceiver, bytes memory signatures ) external payable returns (bool success); - function execTransactionFromModule(address to, uint256 value, bytes memory data, Enum.Operation operation) - external - returns (bool success); - function execTransactionFromModuleReturnData(address to, uint256 value, bytes memory data, Enum.Operation operation) - external - returns (bool success, bytes memory returnData); + function execTransactionFromModule( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) external returns (bool success); + function execTransactionFromModuleReturnData( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) external returns (bool success, bytes memory returnData); function getChainId() external view returns (uint256); function getModulesPaginated(address start, uint256 pageSize) external diff --git a/contracts/src/FunctionGateway.sol b/contracts/src/FunctionGateway.sol index d60c174a3..b07bd3a40 100644 --- a/contracts/src/FunctionGateway.sol +++ b/contracts/src/FunctionGateway.sol @@ -57,7 +57,13 @@ contract FunctionGateway is IFunctionGateway, FunctionRegistry, TimelockedUpgrad bytes32 contextHash = keccak256(_context); address callbackAddress = msg.sender; bytes32 requestHash = _requestHash( - nonce, _functionId, inputHash, contextHash, callbackAddress, _callbackSelector, _callbackGasLimit + nonce, + _functionId, + inputHash, + contextHash, + callbackAddress, + _callbackSelector, + _callbackGasLimit ); // Increment the nonce. @@ -66,7 +72,13 @@ contract FunctionGateway is IFunctionGateway, FunctionRegistry, TimelockedUpgrad // Store the callback hash. requests[nonce] = requestHash; emit RequestCallback( - nonce, _functionId, _input, _context, callbackAddress, _callbackSelector, _callbackGasLimit + nonce, + _functionId, + _input, + _context, + callbackAddress, + _callbackSelector, + _callbackGasLimit ); // Send the fee to the vault. @@ -81,10 +93,12 @@ contract FunctionGateway is IFunctionGateway, FunctionRegistry, TimelockedUpgrad /// @param _input The function input. /// @param _address The address of the callback contract. /// @param _data The data for the callback function. - function requestCall(bytes32 _functionId, bytes memory _input, address _address, bytes memory _data) - external - payable - { + function requestCall( + bytes32 _functionId, + bytes memory _input, + address _address, + bytes memory _data + ) external payable { // Emit event. emit RequestCall(_functionId, _input, _address, _data); @@ -96,7 +110,11 @@ contract FunctionGateway is IFunctionGateway, FunctionRegistry, TimelockedUpgrad /// this function reverts. /// @param _functionId The function identifier. /// @param _input The function input. - function verifiedCall(bytes32 _functionId, bytes memory _input) external view returns (bytes memory) { + function verifiedCall(bytes32 _functionId, bytes memory _input) + external + view + returns (bytes memory) + { bytes32 inputHash = sha256(_input); if (verifiedFunctionId == _functionId && verifiedInputHash == inputHash) { return verifiedOutput; @@ -129,7 +147,13 @@ contract FunctionGateway is IFunctionGateway, FunctionRegistry, TimelockedUpgrad // Reconstruct the callback hash. bytes32 contextHash = keccak256(_context); bytes32 requestHash = _requestHash( - _nonce, _functionId, _inputHash, contextHash, _callbackAddress, _callbackSelector, _callbackGasLimit + _nonce, + _functionId, + _inputHash, + contextHash, + _callbackAddress, + _callbackSelector, + _callbackGasLimit ); // Assert that the callback hash is unfilfilled. @@ -148,7 +172,8 @@ contract FunctionGateway is IFunctionGateway, FunctionRegistry, TimelockedUpgrad // Execute the callback. isCallback = true; - (bool status,) = _callbackAddress.call(abi.encodeWithSelector(_callbackSelector, _output, _context)); + (bool status,) = + _callbackAddress.call(abi.encodeWithSelector(_callbackSelector, _output, _context)); isCallback = false; // If the callback failed, revert. @@ -220,7 +245,13 @@ contract FunctionGateway is IFunctionGateway, FunctionRegistry, TimelockedUpgrad ) internal pure returns (bytes32) { return keccak256( abi.encodePacked( - _nonce, _functionId, _inputHash, _contextHash, _callbackAddress, _callbackSelector, _callbackGasLimit + _nonce, + _functionId, + _inputHash, + _contextHash, + _callbackAddress, + _callbackSelector, + _callbackGasLimit ) ); } @@ -230,7 +261,12 @@ contract FunctionGateway is IFunctionGateway, FunctionRegistry, TimelockedUpgrad /// @param _inputHash The hash of the function input. /// @param _outputHash The hash of the function output. /// @param _proof The function proof. - function _verify(bytes32 _functionId, bytes32 _inputHash, bytes32 _outputHash, bytes memory _proof) internal { + function _verify( + bytes32 _functionId, + bytes32 _inputHash, + bytes32 _outputHash, + bytes memory _proof + ) internal { address verifier = verifiers[_functionId]; if (!IFunctionVerifier(verifier).verify(_inputHash, _outputHash, _proof)) { revert InvalidProof(address(verifier), _inputHash, _outputHash, _proof); diff --git a/contracts/src/FunctionRegistry.sol b/contracts/src/FunctionRegistry.sol index bb24d8a9f..3ace65193 100644 --- a/contracts/src/FunctionRegistry.sol +++ b/contracts/src/FunctionRegistry.sol @@ -13,7 +13,10 @@ contract FunctionRegistry is IFunctionRegistry { /// @notice Registers a function, using a pre-deployed verifier. /// @param _verifier The address of the verifier. /// @param _name The name of the function to be registered. - function registerFunction(address _verifier, string memory _name) external returns (bytes32 functionId) { + function registerFunction(address _verifier, string memory _name) + external + returns (bytes32 functionId) + { functionId = getFunctionId(msg.sender, _name); if (address(verifiers[functionId]) != address(0)) { revert FunctionAlreadyRegistered(functionId); // should call update instead @@ -49,7 +52,10 @@ contract FunctionRegistry is IFunctionRegistry { /// @notice Updates the function, using a pre-deployed verifier. /// @param _verifier The address of the verifier. /// @param _name The name of the function to be updated. - function updateFunction(address _verifier, string memory _name) external returns (bytes32 functionId) { + function updateFunction(address _verifier, string memory _name) + external + returns (bytes32 functionId) + { functionId = getFunctionId(msg.sender, _name); if (msg.sender != verifierOwners[functionId]) { revert NotFunctionOwner(msg.sender, verifierOwners[functionId]); @@ -82,11 +88,18 @@ contract FunctionRegistry is IFunctionRegistry { /// @notice Returns the functionId for a given owner and function name. /// @param _owner The owner of the function (sender of registerFunction). /// @param _name The name of the function. - function getFunctionId(address _owner, string memory _name) public pure returns (bytes32 functionId) { + function getFunctionId(address _owner, string memory _name) + public + pure + returns (bytes32 functionId) + { functionId = keccak256(abi.encode(_owner, _name)); } - function _deploy(bytes memory _bytecode, bytes32 _salt) internal returns (address deployedAddr) { + function _deploy(bytes memory _bytecode, bytes32 _salt) + internal + returns (address deployedAddr) + { if (_bytecode.length == 0) revert EmptyBytecode(); assembly { diff --git a/contracts/src/interfaces/IFunctionGateway.sol b/contracts/src/interfaces/IFunctionGateway.sol index 7ca4c1b41..e969f7176 100644 --- a/contracts/src/interfaces/IFunctionGateway.sol +++ b/contracts/src/interfaces/IFunctionGateway.sol @@ -11,8 +11,12 @@ interface IFunctionGatewayEvents { bytes4 callbackSelector, uint32 callbackGasLimit ); - event RequestCall(bytes32 indexed functionId, bytes input, address callbackAddress, bytes callbackData); - event RequestFulfilled(uint32 indexed nonce, bytes32 indexed functionId, bytes32 inputHash, bytes32 outputHash); + event RequestCall( + bytes32 indexed functionId, bytes input, address callbackAddress, bytes callbackData + ); + event RequestFulfilled( + uint32 indexed nonce, bytes32 indexed functionId, bytes32 inputHash, bytes32 outputHash + ); event Call(bytes32 indexed functionId, bytes32 inputHash, bytes32 outputHash); } @@ -33,9 +37,15 @@ interface IFunctionGateway is IFunctionGatewayEvents, IFunctionGatewayErrors { uint32 _callbackGasLimit ) external payable returns (bytes32); - function requestCall(bytes32 _functionId, bytes memory _input, address _callbackAddress, bytes memory _callbackData) - external - payable; + function requestCall( + bytes32 _functionId, + bytes memory _input, + address _callbackAddress, + bytes memory _callbackData + ) external payable; - function verifiedCall(bytes32 _functionId, bytes memory _input) external view returns (bytes memory); + function verifiedCall(bytes32 _functionId, bytes memory _input) + external + view + returns (bytes memory); } diff --git a/contracts/src/interfaces/IFunctionRegistry.sol b/contracts/src/interfaces/IFunctionRegistry.sol index 1797f7261..697886040 100644 --- a/contracts/src/interfaces/IFunctionRegistry.sol +++ b/contracts/src/interfaces/IFunctionRegistry.sol @@ -2,10 +2,14 @@ pragma solidity >=0.5.0; interface IFunctionRegistryEvents { - event FunctionRegistered(bytes32 indexed functionId, address verifier, string name, address owner); + event FunctionRegistered( + bytes32 indexed functionId, address verifier, string name, address owner + ); event FunctionVerifierUpdated(bytes32 indexed functionId, address verifier); event FunctionOwnerUpdated(bytes32 indexed functionId, address owner); - event Deployed(bytes32 indexed bytecodeHash, bytes32 indexed salt, address indexed deployedAddress); + event Deployed( + bytes32 indexed bytecodeHash, bytes32 indexed salt, address indexed deployedAddress + ); } interface IFunctionRegistryErrors { @@ -19,13 +23,20 @@ interface IFunctionRegistryErrors { interface IFunctionRegistry is IFunctionRegistryEvents, IFunctionRegistryErrors { function verifiers(bytes32 functionId) external view returns (address verifier); function verifierOwners(bytes32 functionId) external view returns (address owner); - function registerFunction(address verifier, string memory name) external returns (bytes32 functionId); + function registerFunction(address verifier, string memory name) + external + returns (bytes32 functionId); function deployAndRegisterFunction(bytes memory bytecode, string memory name) external returns (bytes32 functionId, address verifier); - function updateFunction(address verifier, string memory name) external returns (bytes32 functionId); + function updateFunction(address verifier, string memory name) + external + returns (bytes32 functionId); function deployAndUpdateFunction(bytes memory bytecode, string memory _name) external returns (bytes32 functionId, address verifier); - function getFunctionId(address owner, string memory name) external pure returns (bytes32 functionId); + function getFunctionId(address owner, string memory name) + external + pure + returns (bytes32 functionId); } diff --git a/contracts/src/interfaces/IFunctionVerifier.sol b/contracts/src/interfaces/IFunctionVerifier.sol index 1c5817c9d..7b8652557 100644 --- a/contracts/src/interfaces/IFunctionVerifier.sol +++ b/contracts/src/interfaces/IFunctionVerifier.sol @@ -2,7 +2,9 @@ pragma solidity >=0.5.0; interface IFunctionVerifier { - function verify(bytes32 inputHash, bytes32 outputHash, bytes memory proof) external returns (bool); + function verify(bytes32 inputHash, bytes32 outputHash, bytes memory proof) + external + returns (bool); function verificationKeyHash() external view returns (bytes32); } diff --git a/contracts/src/libraries/OutputReader.sol b/contracts/src/libraries/OutputReader.sol index 48cc7efe6..f52c57bc6 100644 --- a/contracts/src/libraries/OutputReader.sol +++ b/contracts/src/libraries/OutputReader.sol @@ -1,7 +1,11 @@ pragma solidity ^0.8.16; library OutputReader { - function readUint256(bytes memory _output, uint256 _offset) internal pure returns (uint256, uint256) { + function readUint256(bytes memory _output, uint256 _offset) + internal + pure + returns (uint256, uint256) + { uint256 value; assembly { value := mload(add(add(_output, 0x20), _offset)) @@ -9,7 +13,11 @@ library OutputReader { return (_offset + 32, value); } - function readUint128(bytes memory _output, uint256 _offset) internal pure returns (uint256, uint128) { + function readUint128(bytes memory _output, uint256 _offset) + internal + pure + returns (uint256, uint128) + { uint128 value; assembly { value := mload(add(add(_output, 0x10), _offset)) @@ -17,7 +25,11 @@ library OutputReader { return (_offset + 16, value); } - function readUint64(bytes memory _output, uint256 _offset) internal pure returns (uint256, uint64) { + function readUint64(bytes memory _output, uint256 _offset) + internal + pure + returns (uint256, uint64) + { uint64 value; assembly { value := mload(add(add(_output, 0x08), _offset)) @@ -25,7 +37,11 @@ library OutputReader { return (_offset + 8, value); } - function readUint32(bytes memory _output, uint256 _offset) internal pure returns (uint256, uint32) { + function readUint32(bytes memory _output, uint256 _offset) + internal + pure + returns (uint256, uint32) + { uint32 value; assembly { value := mload(add(add(_output, 0x04), _offset)) diff --git a/contracts/src/upgrades/Timelock.sol b/contracts/src/upgrades/Timelock.sol index 817c733ad..a505b37c6 100644 --- a/contracts/src/upgrades/Timelock.sol +++ b/contracts/src/upgrades/Timelock.sol @@ -10,7 +10,10 @@ contract Timelock is TimelockController { /// @param _proposers accounts to be granted proposer and canceller roles /// @param _executors accounts to be granted executor role /// @param _admin optional account to be granted admin role; disable with zero address - constructor(uint256 _minDelay, address[] memory _proposers, address[] memory _executors, address _admin) - TimelockController(_minDelay, _proposers, _executors, _admin) - {} + constructor( + uint256 _minDelay, + address[] memory _proposers, + address[] memory _executors, + address _admin + ) TimelockController(_minDelay, _proposers, _executors, _admin) {} } diff --git a/contracts/src/upgrades/TimelockedUpgradeable.sol b/contracts/src/upgrades/TimelockedUpgradeable.sol index 7d0386941..9dacdcf9a 100644 --- a/contracts/src/upgrades/TimelockedUpgradeable.sol +++ b/contracts/src/upgrades/TimelockedUpgradeable.sol @@ -4,12 +4,18 @@ pragma solidity ^0.8.16; import {Versioned} from "./Versioned.sol"; import {Initializable} from "@openzeppelin-upgradeable/contracts/proxy/utils/Initializable.sol"; import {UUPSUpgradeable} from "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; -import {AccessControlUpgradeable} from "@openzeppelin-upgradeable/contracts/access/AccessControlUpgradeable.sol"; +import {AccessControlUpgradeable} from + "@openzeppelin-upgradeable/contracts/access/AccessControlUpgradeable.sol"; /// @title TimelockedUpgradeable /// @notice A base contract that has modifiers to specify that certain functions are only callable /// by a sender with a timelock or guardian role. -abstract contract TimelockedUpgradeable is Versioned, Initializable, UUPSUpgradeable, AccessControlUpgradeable { +abstract contract TimelockedUpgradeable is + Versioned, + Initializable, + UUPSUpgradeable, + AccessControlUpgradeable +{ /// @notice A random constant used to identify addresses with the permission of a 'timelock'. /// @dev Should be set to a 'timelock' contract, which may only execute calls after being /// for a certain amount of time. @@ -43,7 +49,10 @@ abstract contract TimelockedUpgradeable is Versioned, Initializable, UUPSUpgrade /// @notice Initializes the contract. /// @dev The DEFAULT_ADMIN_ROLE needs to be set but should be unused. - function __TimelockedUpgradeable_init(address _timelock, address _guardian) internal onlyInitializing { + function __TimelockedUpgradeable_init(address _timelock, address _guardian) + internal + onlyInitializing + { __AccessControl_init(); __UUPSUpgradeable_init(); _grantRole(DEFAULT_ADMIN_ROLE, _timelock);