From bfd57bd37bd866c7ddb13cf16c0c72fbc92d5e8b Mon Sep 17 00:00:00 2001 From: dndll Date: Tue, 13 Feb 2024 17:43:31 +0000 Subject: [PATCH] wip: contracts --- .gitignore | 16 +- .gitmodules | 9 ++ Cargo.toml | 8 +- Makefile | 32 ++++ bin/operator/src/main.rs | 2 + .../{contracts => contract}/README.md | 0 circuits/plonky2x/contract/foundry.toml | 7 + .../plonky2x/contract/script/Deploy.s.sol | 28 ++++ .../plonky2x/contract/script/Initialise.s.sol | 34 +++++ .../plonky2x/contract/script/Upgrade.s.sol | 34 +++++ circuits/plonky2x/contract/src/NearX.sol | 129 ++++++++++++++++ .../contract/src/interfaces/INearX.sol | 85 +++++++++++ .../src/interfaces/ISuccinctGateway.sol | 0 circuits/plonky2x/contract/test/NearX.t.sol | 43 ++++++ circuits/plonky2x/contracts/foundry.toml | 6 - .../plonky2x/contracts/script/Deploy.s.sol | 28 ---- circuits/plonky2x/contracts/src/NearX.sol | 140 ------------------ .../contracts/src/interfaces/INearX.sol | 31 ---- circuits/plonky2x/contracts/test/NearX.t.sol | 28 ---- circuits/plonky2x/src/circuits/mod.rs | 1 + circuits/plonky2x/src/circuits/verify.rs | 7 +- fixtures/input.bytes.json | 1 - 22 files changed, 419 insertions(+), 250 deletions(-) rename circuits/plonky2x/{contracts => contract}/README.md (100%) create mode 100644 circuits/plonky2x/contract/foundry.toml create mode 100644 circuits/plonky2x/contract/script/Deploy.s.sol create mode 100644 circuits/plonky2x/contract/script/Initialise.s.sol create mode 100644 circuits/plonky2x/contract/script/Upgrade.s.sol create mode 100644 circuits/plonky2x/contract/src/NearX.sol create mode 100644 circuits/plonky2x/contract/src/interfaces/INearX.sol rename circuits/plonky2x/{contracts => contract}/src/interfaces/ISuccinctGateway.sol (100%) create mode 100644 circuits/plonky2x/contract/test/NearX.t.sol delete mode 100644 circuits/plonky2x/contracts/foundry.toml delete mode 100644 circuits/plonky2x/contracts/script/Deploy.s.sol delete mode 100644 circuits/plonky2x/contracts/src/NearX.sol delete mode 100644 circuits/plonky2x/contracts/src/interfaces/INearX.sol delete mode 100644 circuits/plonky2x/contracts/test/NearX.t.sol delete mode 100644 fixtures/input.bytes.json diff --git a/.gitignore b/.gitignore index 880e03b..0bbdff0 100644 --- a/.gitignore +++ b/.gitignore @@ -10,16 +10,18 @@ local.toml *.db # Compiler files -circuits/plonky2x/contracts/cache -circuits/plonky2x/contracts/out -circuits/plonky2x/contracts/lib +circuits/plonky2x/contract/cache +circuits/plonky2x/contract/out +circuits/plonky2x/contract/lib +# Ignores development broadcast logs +!**broadcast +**broadcast/*/31337/ +**broadcast/**/dry-run/ +circuits/plonky2x/contract/broadcast + wrapped/ build/ -# Ignores development broadcast logs -!/broadcast -/broadcast/*/31337/ -/broadcast/**/dry-run/ # Docs docs/ diff --git a/.gitmodules b/.gitmodules index 817cb6f..f34d21e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,12 @@ [submodule "vendor/succinctx"] path = vendor/succinctx url = git@github.com:succinctlabs/succinctx.git +[submodule "circuits/plonky2x/verifier/lib/openzeppelin-contracts-upgradeable"] + path = circuits/plonky2x/verifier/lib/openzeppelin-contracts-upgradeable + url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable +[submodule "circuits/plonky2x/verifier/lib/openzeppelin-contracts"] + path = circuits/plonky2x/verifier/lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts +[submodule "circuits/plonky2x/verifier/lib/foundry-devops"] + path = circuits/plonky2x/verifier/lib/foundry-devops + url = https://github.com/chainaccelorg/foundry-devops diff --git a/Cargo.toml b/Cargo.toml index fdeb375..961b35b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,9 +52,9 @@ test-utils = { path = "crates/test-utils" } curta = { git = "https://github.com/dndll/starkyx.git" } [patch."https://github.com/succinctlabs/starkyx.git"] -#curta = { path = "./vendor/starkyx/curta" } -curta = { git = "https://github.com/dndll/starkyx.git" } +curta = { path = "./vendor/starkyx/curta" } +#curta = { git = "https://github.com/dndll/starkyx.git" } [patch."https://github.com/succinctlabs/succinctx.git"] -#plonky2x = { path = "./vendor/succinctx/plonky2x/core" } -plonky2x = { git = "https://github.com/dndll/succinctx.git" } +plonky2x = { path = "./vendor/succinctx/plonky2x/core" } +#plonky2x = { git = "https://github.com/dndll/succinctx.git" } diff --git a/Makefile b/Makefile index da531fb..cd22ecc 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,6 @@ +.EXPORT_ALL_VARIABLES: +include .env + TAG_PREFIX?=near IMAGE_TAG?=0.0.1 @@ -20,3 +23,32 @@ build-verify-circuit: RUST_LOG=debug ./build/verify build .PHONY: build-verify-circuit + +SYNC_FUNCTION_ID=0x350c2939eb7ff2185612710a2b641b4b46faab68e1e2c57b6f15e0af0674f5e9 +VERIFY_FUNCTION_ID=0x39fb2562b80725bb7538dd7d850126964e565a1a837d2d7f2a018e185b08fc0e +ETH_RPC=https://goerli.gateway.tenderly.co +NEAR_CHECKPOINT_HEADER_HASH=0x63b87190ffbaa36d7dab50f918fe36f70ab26910a0e9d797161e2356561598e3 +CHAIN_ID=5 +CD_CONTRACTS=cd ./circuits/plonky2x/contract + +build-contracts: + $(CD_CONTRACTS) && forge build + +deploy: build-contracts + $(CD_CONTRACTS) && forge script Deploy \ + --rpc-url $(ETH_RPC) \ + --private-key $$ETH_PRIVATE_KEY \ + --broadcast \ + --verify \ + --verifier etherscan + +initialise: + cd $(ETH_CONTRACTS_PATH) && forge script Initialise \ + --rpc-url $(ETH_RPC) \ + --private-key $$ETH_PRIVATE_KEY \ + --broadcast \ + --verify \ + --verifier etherscan + +# TODO: upgrade + diff --git a/bin/operator/src/main.rs b/bin/operator/src/main.rs index 8f73b8b..24ee4e8 100644 --- a/bin/operator/src/main.rs +++ b/bin/operator/src/main.rs @@ -11,6 +11,8 @@ cfg_if::cfg_if! { } } +// TODO: make this use a nicer API for use by the prover. +// TODO: perpetually sync, use queue etc fn main() { cfg_if::cfg_if! { if #[cfg(feature = "sync")] { diff --git a/circuits/plonky2x/contracts/README.md b/circuits/plonky2x/contract/README.md similarity index 100% rename from circuits/plonky2x/contracts/README.md rename to circuits/plonky2x/contract/README.md diff --git a/circuits/plonky2x/contract/foundry.toml b/circuits/plonky2x/contract/foundry.toml new file mode 100644 index 0000000..15402f9 --- /dev/null +++ b/circuits/plonky2x/contract/foundry.toml @@ -0,0 +1,7 @@ +[profile.default] +fs_permissions = [ { access = "read", path = "./broadcast" } ] +libs = [ "lib" ] +out = "out" +remappings = [ "@openzeppelin/contracts=lib/openzeppelin-contracts/contracts", "@openzeppelin/contracts-upgradeable=lib/openzeppelin-contracts-upgradeable/contracts" ] +src = "src" +# See more config options https://github.com/foundry-rs/foundry/tree/master/config diff --git a/circuits/plonky2x/contract/script/Deploy.s.sol b/circuits/plonky2x/contract/script/Deploy.s.sol new file mode 100644 index 0000000..4e3042a --- /dev/null +++ b/circuits/plonky2x/contract/script/Deploy.s.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.19; + +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import {NearX} from "../src/NearX.sol"; +import {Script} from "forge-std/Script.sol"; + +contract Deploy is Script { + function setUp() public {} + + function run() external returns (address) { + address proxy = deployNearX(); + return proxy; + } + + function deployNearX() public returns (address) { + vm.startBroadcast(); + + NearX lightClient = new NearX(); + + ERC1967Proxy proxy = new ERC1967Proxy(address(lightClient), ""); + + lightClient.initialize(); + + vm.stopBroadcast(); + return address(proxy); + } +} diff --git a/circuits/plonky2x/contract/script/Initialise.s.sol b/circuits/plonky2x/contract/script/Initialise.s.sol new file mode 100644 index 0000000..c8ae6ce --- /dev/null +++ b/circuits/plonky2x/contract/script/Initialise.s.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.19; + +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import {NearX} from "../src/NearX.sol"; +import {Script} from "forge-std/Script.sol"; +import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol"; + +contract Initialise is Script { + function setUp() public {} + + function run() external { + address proxyAddress = DevOpsTools.get_most_recent_deployment( + "ERC1967Proxy", + block.chainid + ); + vm.startBroadcast(); + NearX lightClient = NearX(payable(proxyAddress)); + + address initialGateway = 0x6e4f1e9eA315EBFd69d18C2DB974EEf6105FB803; + lightClient.updateGateway(initialGateway); + + bytes32 syncFunctionId = vm.envBytes32("SYNC_FUNCTION_ID"); + lightClient.updateSyncId(syncFunctionId); + + bytes32 verifyFunctionId = vm.envBytes32("VERIFY_FUNCTION_ID"); + lightClient.updateVerifyId(verifyFunctionId); + + bytes32 header = vm.envBytes32("NEAR_CHECKPOINT_HEADER_HASH"); + lightClient.setCheckpointHeader(header); + + vm.stopBroadcast(); + } +} diff --git a/circuits/plonky2x/contract/script/Upgrade.s.sol b/circuits/plonky2x/contract/script/Upgrade.s.sol new file mode 100644 index 0000000..5a654af --- /dev/null +++ b/circuits/plonky2x/contract/script/Upgrade.s.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Script} from "forge-std/Script.sol"; +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol"; +import {NearX} from "../src/NearX.sol"; + +contract Upgrade is Script { + function run() external returns (address) { + address mostRecentlyDeployedProxy = DevOpsTools + .get_most_recent_deployment("ERC1967Proxy", block.chainid); + vm.startBroadcast(); + + NearX newAddress = new NearX(); + + vm.stopBroadcast(); + address proxy = upgrade(mostRecentlyDeployedProxy, address(newAddress)); + return proxy; + } + + function upgrade(address proxyAddress, address newAddress) + public + returns (address) + { + vm.startBroadcast(); + + NearX proxy = NearX(payable(proxyAddress)); + proxy.upgradeToAndCall(address(newAddress), ""); + + vm.stopBroadcast(); + return address(proxy); + } +} diff --git a/circuits/plonky2x/contract/src/NearX.sol b/circuits/plonky2x/contract/src/NearX.sol new file mode 100644 index 0000000..a71adb4 --- /dev/null +++ b/circuits/plonky2x/contract/src/NearX.sol @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {ISuccinctGateway} from "./interfaces/ISuccinctGateway.sol"; +import {INearX, TransactionOrReceiptId, encodePackedIds, decodePackedIds} from "./interfaces/INearX.sol"; + +/// @notice The NearX contract is a light client for Near. +contract NearX is INearX, Initializable, OwnableUpgradeable, UUPSUpgradeable { + uint32 public constant DEFAULT_GAS_LIMIT = 1000000; + + /// @notice The address of the gateway contract. + address public gateway; + + constructor() { + _disableInitializers(); + } + + function initialize() public initializer { + __Ownable_init(msg.sender); //sets owner to msg.sender + __UUPSUpgradeable_init(); + } + + function _authorizeUpgrade(address newImplementation) + internal + override + onlyOwner + {} + + /// @notice Sync function id. + bytes32 public syncFunctionId; + + /// @notice Verify function id. + bytes32 public verifyFunctionId; + + /// @notice The latest header that has been committed. + bytes32 public latestHeader; + + function updateGateway(address _gateway) external onlyOwner { + gateway = _gateway; + } + + function updateSyncId(bytes32 _functionId) external onlyOwner { + syncFunctionId = _functionId; + } + + function updateVerifyId(bytes32 _functionId) external onlyOwner { + verifyFunctionId = _functionId; + } + + /// Note: Only for testnet. The genesis header should be set when initializing the contract. + function setCheckpointHeader(bytes32 _header) external onlyOwner { + latestHeader = _header; + } + + function ensureInitialized() internal view { + if (gateway == address(0)) { + revert GatewayNotInitialised(); + } + if (syncFunctionId == bytes32(0) || verifyFunctionId == bytes32(0)) { + revert FunctionIdsNotInitialised(); + } + if (latestHeader == bytes32(0)) { + revert HeaderNotInitialised(); + } + } + + /// @notice Inputs of a sync request. + function requestSync() external payable { + ensureInitialized(); + bytes memory context; + + ISuccinctGateway(gateway).requestCallback{value: msg.value}( + syncFunctionId, + abi.encodePacked(latestHeader), + context, + NearX.handleSync.selector, + DEFAULT_GAS_LIMIT + ); + + emit SyncRequested(latestHeader); + } + + function handleSync(bytes memory _output, bytes memory _context) external { + if (msg.sender != gateway || !ISuccinctGateway(gateway).isCallback()) { + revert NotFromSuccinctGateway(msg.sender); + } + + bytes32 targetHeader = abi.decode(_output, (bytes32)); + + latestHeader = targetHeader; + + emit HeadUpdate(targetHeader); + } + + function requestVerify(TransactionOrReceiptId[] memory ids) + external + payable + { + ensureInitialized(); + bytes memory context; + bytes memory input = abi.encodePacked( + latestHeader, + encodePackedIds(ids) + ); + + ISuccinctGateway(gateway).requestCallback{value: msg.value}( + verifyFunctionId, + input, + context, + NearX.handleVerify.selector, + DEFAULT_GAS_LIMIT + ); + + emit VerifyRequested(latestHeader, ids); + } + + function handleVerify(bytes memory _output, bytes memory _context) + external + { + if (msg.sender != gateway || !ISuccinctGateway(gateway).isCallback()) { + revert NotFromSuccinctGateway(msg.sender); + } + TransactionOrReceiptId[] memory ids = decodePackedIds(_output); + emit VerifyResult(ids); + } +} diff --git a/circuits/plonky2x/contract/src/interfaces/INearX.sol b/circuits/plonky2x/contract/src/interfaces/INearX.sol new file mode 100644 index 0000000..59d1f3a --- /dev/null +++ b/circuits/plonky2x/contract/src/interfaces/INearX.sol @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +interface INearX { + /// @notice Emits event with the new head update. + event HeadUpdate(bytes32 headerHash); + + /// @notice Inputs of a sync request. + /// @param trustedHeader The header hash of the trusted block. + event SyncRequested(bytes32 indexed trustedHeader); + + /// @notice Inputs of a verify request. + /// @param trustedHeader The header hash of the trusted block. + /// @param ids The transaction or receipt ids to verify. + event VerifyRequested( + bytes32 indexed trustedHeader, + TransactionOrReceiptId[] indexed ids + ); + + /// @notice Trusted header not found. + error TrustedHeaderNotFound(); + + /// @notice Header not Initialised. + error HeaderNotInitialised(); + + /// @notice Not from Succinct Gateway. + error NotFromSuccinctGateway(address); + + error GatewayNotInitialised(); + + error FunctionIdsNotInitialised(); + + /// @notice The result of the verification request + event VerifyResult(TransactionOrReceiptId[] ids); +} + +uint256 constant MAX_LEN = 64; + +struct TransactionOrReceiptId { + bool isTransaction; + bytes32 id; + bytes account; +} + +function encodePackedIds(TransactionOrReceiptId[] memory ids) + pure + returns (bytes memory) +{ + bytes memory output; + for (uint256 i = 0; i < ids.length; i++) { + output = abi.encodePacked( + output, + ids[i].isTransaction, + ids[i].id, + ids[i].account + ); + } + return output; +} + +function decodePackedIds(bytes memory _input) + pure + returns (TransactionOrReceiptId[] memory) +{ + uint256 idsLength = _input.length / 1 + 32 + MAX_LEN; + TransactionOrReceiptId[] memory ids = new TransactionOrReceiptId[]( + idsLength + ); + + for (uint256 i = 0; i < idsLength; i++) { + ids[i] = decodeTransactionOrReceiptId(_input); + } + return ids; +} + +function decodeTransactionOrReceiptId(bytes memory _input) + pure + returns (TransactionOrReceiptId memory id) +{ + id.isTransaction = abi.decode(_input, (bool)); + id.id = abi.decode(_input, (bytes32)); + bytes32 accountX = abi.decode(_input, (bytes32)); + bytes32 accountY = abi.decode(_input, (bytes32)); + id.account = abi.encodePacked(accountX, accountY); +} diff --git a/circuits/plonky2x/contracts/src/interfaces/ISuccinctGateway.sol b/circuits/plonky2x/contract/src/interfaces/ISuccinctGateway.sol similarity index 100% rename from circuits/plonky2x/contracts/src/interfaces/ISuccinctGateway.sol rename to circuits/plonky2x/contract/src/interfaces/ISuccinctGateway.sol diff --git a/circuits/plonky2x/contract/test/NearX.t.sol b/circuits/plonky2x/contract/test/NearX.t.sol new file mode 100644 index 0000000..3859530 --- /dev/null +++ b/circuits/plonky2x/contract/test/NearX.t.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Test.sol"; +import "../src/NearX.sol"; + +contract NearXTest is Test { + NearX public lightClient; + + function setUp() public { + lightClient = new NearX(); + } + + function testGetEncodePackedSync() public view { + // TODO: + bytes32 header = hex"63b87190ffbaa36d7dab50f918fe36f70ab26910a0e9d797161e2356561598e3"; + bytes memory encodedInput = abi.encodePacked(header); + console.logBytes(encodedInput); + } + + function testGetEncodePackedVerify() public view { + // TODO: + bytes32 header = hex"63b87190ffbaa36d7dab50f918fe36f70ab26910a0e9d797161e2356561598e3"; + bytes tx = hex"012c53bcfe871da28decc45c3437f5864568d91af6d990dbc2662f11ce44c18d797a61766f64696c2e746573746e65742c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c"; + bytes rx = hex"007ff581f8517ec58459099a5af2465d5232fdcdd7c4da9c3d42a887bf6bd5457e70726963656f7261636c652e746573746e65742c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c"; + + TransactionOrReceiptId[] memory ids = new TransactionOrReceiptId[](2); + ids[0].isTransaction = true; + ids[0] + .id = hex"63b87190ffbaa36d7dab50f918fe36f70ab26910a0e9d797161e2356561598e3"; + ids[1].isTransaction = false; + ids[1] + .id = hex"63b87190ffbaa36d7dab50f918fe36f70ab26910a0e9d797161e2356561598e3"; + ids[1] + .account = hex"0000000000000000000000000000000000000000000000000000000000000000"; + bytes memory encodedInput = abi.encodePacked( + latestHeader, + encodePackedIds(ids) + ); + + console.logBytes(encodedInput); + } +} diff --git a/circuits/plonky2x/contracts/foundry.toml b/circuits/plonky2x/contracts/foundry.toml deleted file mode 100644 index e883058..0000000 --- a/circuits/plonky2x/contracts/foundry.toml +++ /dev/null @@ -1,6 +0,0 @@ -[profile.default] -src = "src" -out = "out" -libs = ["lib"] - -# See more config options https://github.com/foundry-rs/foundry/tree/master/config diff --git a/circuits/plonky2x/contracts/script/Deploy.s.sol b/circuits/plonky2x/contracts/script/Deploy.s.sol deleted file mode 100644 index 1ff9864..0000000 --- a/circuits/plonky2x/contracts/script/Deploy.s.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "forge-std/Script.sol"; -import {NearX} from "../src/NearX.sol"; - -contract DeployScript is Script { - function setUp() public {} - - function run() public { - vm.startBroadcast(); - - address gateway = 0x6e4f1e9eA315EBFd69d18C2DB974EEf6105FB803; - - // Use the below to interact with an already deployed ZK light client. - NearX lightClient = new NearX(gateway); - - bytes32 syncFunctionId = vm.envBytes32("SYNC_FUNCTION_ID"); - lightClient.updateSyncId(syncFunctionId); - - bytes32 verifyFunctionId = vm.envBytes32("VERIFY_FUNCTION_ID"); - lightClient.updateVerifyId(verifyFunctionId); - - uint64 height = uint64(vm.envUint("GENESIS_HEIGHT")); - bytes32 header = vm.envBytes32("GENESIS_HEADER"); - lightClient.setGenesisHeader(header); - } -} diff --git a/circuits/plonky2x/contracts/src/NearX.sol b/circuits/plonky2x/contracts/src/NearX.sol deleted file mode 100644 index 12c8eb9..0000000 --- a/circuits/plonky2x/contracts/src/NearX.sol +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.13; - -import {ISuccinctGateway} from "./interfaces/ISuccinctGateway.sol"; -import {INearX, TransactionOrReceiptId} from "./interfaces/INearX.sol"; - -/// @notice The NearX contract is a light client for Near. -/// @dev -contract NearX is INearX { - /// TODO: integrate this in a nice way - uint64 public constant NETWORK = 1; - - /// @notice The address of the gateway contract. - address public gateway; - - /// @notice The latest header that has been committed. - bytes32 public latestHeader; - - /// @notice Sync function id. - bytes32 public syncFunctionId; - - /// @notice Verify function id. - bytes32 public verifyFunctionId; - - /// @notice Initialize the contract with the address of the gateway contract. - constructor(address _gateway) { - gateway = _gateway; - } - - /// @notice Update the address of the gateway contract. - function updateGateway(address _gateway) external { - gateway = _gateway; - } - - /// @notice Update the function ID for header range. - function updateSyncId(bytes32 _functionId) external { - syncFunctionId = _functionId; - } - - /// @notice Update the function ID for next header. - function updateVerifyId(bytes32 _functionId) external { - verifyFunctionId = _functionId; - } - - /// Note: Only for testnet. The genesis header should be set when initializing the contract. - function setGenesisHeader(bytes32 _header) external { - latestHeader = _header; - } - - function ensureInitialized() internal { - if (latestHeader == bytes32(0)) { - revert HeaderNotInitialised(); - } - } - - /// @notice Inputs of a sync request. - function requestSync() external payable { - ensureInitialized(); - - ISuccinctGateway(gateway).requestCall{value: msg.value}( - syncFunctionId, - abi.encodePacked(latestHeader), - address(this), - abi.encodeWithSelector(this.sync.selector, latestHeader), - 500000 - ); - - emit SyncRequested(latestHeader); - } - - /// @notice Stores the new header for targetBlock. - function sync() external { - ensureInitialized(); - - // Encode the circuit input. - bytes memory input = abi.encodePacked(latestHeader); - - // Call gateway to get the proof result. - bytes memory requestResult = ISuccinctGateway(gateway).verifiedCall( - syncFunctionId, - input - ); - - // Read the target header from request result. - bytes32 targetHeader = abi.decode(requestResult, (bytes32)); - - latestHeader = targetHeader; - - emit HeadUpdate(targetHeader); - } - - function requestVerify(TransactionOrReceiptId[] memory ids) - external - payable - { - ensureInitialized(); - - ISuccinctGateway(gateway).requestCall{value: msg.value}( - verifyFunctionId, - abi.encodePacked(latestHeader, encodePackedIds(ids)), - address(this), - abi.encodeWithSelector(this.verify.selector, latestHeader, ids), - 500000 - ); - emit VerifyRequested(latestHeader, ids); - } - - function verify(TransactionOrReceiptId[] memory ids) external { - ensureInitialized(); - - bytes memory input = abi.encodePacked( - latestHeader, - encodePackedIds(ids) - ); - - // Call gateway to get the proof result. - bytes memory requestResult = ISuccinctGateway(gateway).verifiedCall( - verifyFunctionId, - input - ); - // TODO: emit event for the ids and their verification status - } - - function encodePackedIds(TransactionOrReceiptId[] memory ids) - internal - pure - returns (bytes memory) - { - bytes memory output; - for (uint256 i = 0; i < ids.length; i++) { - output = abi.encodePacked( - output, - ids[i].isTransaction, - ids[i].id, - ids[i].account - ); - } - return output; - } -} diff --git a/circuits/plonky2x/contracts/src/interfaces/INearX.sol b/circuits/plonky2x/contracts/src/interfaces/INearX.sol deleted file mode 100644 index 9de34d5..0000000 --- a/circuits/plonky2x/contracts/src/interfaces/INearX.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -interface INearX { - /// @notice Emits event with the new head update. - event HeadUpdate(bytes32 headerHash); - - /// @notice Inputs of a sync request. - /// @param trustedHeader The header hash of the trusted block. - event SyncRequested(bytes32 indexed trustedHeader); - - /// @notice Inputs of a verify request. - /// @param trustedHeader The header hash of the trusted block. - /// @param ids The transaction or receipt ids to verify. - event VerifyRequested( - bytes32 indexed trustedHeader, - TransactionOrReceiptId[] indexed ids - ); - - /// @notice Trusted header not found. - error TrustedHeaderNotFound(); - - /// @notice Header not Initialised. - error HeaderNotInitialised(); -} - -struct TransactionOrReceiptId { - bool isTransaction; - bytes32 id; - string account; -} diff --git a/circuits/plonky2x/contracts/test/NearX.t.sol b/circuits/plonky2x/contracts/test/NearX.t.sol deleted file mode 100644 index 0c5fa53..0000000 --- a/circuits/plonky2x/contracts/test/NearX.t.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "forge-std/Test.sol"; -import "../src/NearX.sol"; - -contract NearXTest is Test { - NearX public lightClient; - - function setUp() public { - lightClient = new NearX(address(0)); - } - - function testGetEncodePackedSync() public view { - // TODO: - bytes32 header = hex"63b87190ffbaa36d7dab50f918fe36f70ab26910a0e9d797161e2356561598e3"; - bytes memory encodedInput = abi.encodePacked(header); - console.logBytes(encodedInput); - } - - function testGetEncodePackedVerify() public view { - // TODO: - bytes32 header = hex"63b87190ffbaa36d7dab50f918fe36f70ab26910a0e9d797161e2356561598e3"; - - bytes memory encodedInput = abi.encodePacked(header); - console.logBytes(encodedInput); - } -} diff --git a/circuits/plonky2x/src/circuits/mod.rs b/circuits/plonky2x/src/circuits/mod.rs index 3b2075c..a1c8e4c 100644 --- a/circuits/plonky2x/src/circuits/mod.rs +++ b/circuits/plonky2x/src/circuits/mod.rs @@ -1,5 +1,6 @@ pub mod sync; pub mod verify; +// TODO: CIRCUIT SERIALISATION TESTS!!! pub use sync::SyncCircuit; pub use verify::VerifyCircuit; diff --git a/circuits/plonky2x/src/circuits/verify.rs b/circuits/plonky2x/src/circuits/verify.rs index 86b5b0d..cd5d103 100644 --- a/circuits/plonky2x/src/circuits/verify.rs +++ b/circuits/plonky2x/src/circuits/verify.rs @@ -15,17 +15,14 @@ use crate::{ }, }; +pub type ProofMapReduceVariable = ArrayVariable; + #[derive(CircuitVariable, Debug, Clone)] pub struct ProofVerificationResultVariable { pub id: CryptoHashVariable, pub result: BoolVariable, } -// TODO: improve the way we can lookup the transaction, ideally map -// TransactionOrReceiptId => Proof and map this way, now we are not limited by -// the data transformation -pub type ProofMapReduceVariable = ArrayVariable; - #[derive(Debug, Clone)] pub struct VerifyCircuit; diff --git a/fixtures/input.bytes.json b/fixtures/input.bytes.json deleted file mode 100644 index 1091cdf..0000000 --- a/fixtures/input.bytes.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"req_bytes","releaseId":"todo","parentId":null,"files":null,"data":{"input":"0x44cf18d28ab7b9f7f5adb3cf3fd6d8a2a4f93f8fdad01a9e86ae4b5b2b17836fba9c6629085351fbea47cdc2851d8f76c940dcba41702fb91a4b832857734ce8000000000937d838dce68dd6fb22e016c8405dfbfdc90f4a9cef98e5fb3c7afc0e1f46a2b5e11022daf909af5b24b30011f952baccbdab560b1e16bd2d16efabb9f2ee3ffee398fad05d5c913e8db18af4d1fda9f2a18595ac481a324b9f94b02abc18595a39ad365fb163b24a02808b1fe26cd012313376d914a7e58017c722062aba155f9a078117aa90ce2853e1558ec8ea8e1910a48364bfb4faf1085779ad3f4311ff5b7af12c8f20a0ad34a56928328499c4518899bcc03deb1eb9b8247f88c65d6c0cf8cd4b46cf5bce18a0e2012c53bcfe871da28decc45c3437f5864568d91af6d990dbc2662f11ce44c18d797a61766f64696c2e746573746e65742c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c007ff581f8517ec58459099a5af2465d5232fdcdd7c4da9c3d42a887bf6bd5457e70726963656f7261636c652e746573746e65742c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c"}} \ No newline at end of file