Skip to content

Commit

Permalink
feat: crosschain integration (#23)
Browse files Browse the repository at this point in the history
* feat: update for axiom-client v2.1.0

* feat: initial crosschain edits

* feat: update @axiom-crypto/circuit to v2.1.0

* feat: update prove CLI for crosschain

* feat: update interfaces to specify crosschain

* feat: update axiom-std for crosschain

* fix: address comments on address conventions

* wip: checkpoint

* fix: update crosschain configuration to include targetRpcUrl

* chore: add additional secret to CI

* feat: update axiom-client version

* fix: update call

* feat: enable usage of chains without pre-existing deployments in axiom-std (#25)

* feat: enable usage of chains without pre-existing deployments in axiom-std

* chore: update axiom-client

* chore: update axiom-client

* chore: fix CI

* Fix crosschain run function (#27)

* chore: bump SDK version

* chore: add Base Sepolia cross-chain address

---------

Co-authored-by: Yu Jiang Tham <[email protected]>
  • Loading branch information
yi-sun and ytham authored Jul 17, 2024
1 parent e47d118 commit b406ae6
Show file tree
Hide file tree
Showing 16 changed files with 860 additions and 447 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ jobs:

- name: Run Foundry tests
run: |
export PROVIDER_URI_MAINNET=${{ secrets.PROVIDER_URI_MAINNET }}
export PROVIDER_URI_SEPOLIA=${{ secrets.PROVIDER_URI_SEPOLIA }}
export PROVIDER_URI_BASE=${{ secrets.PROVIDER_URI_BASE }}
export PROVIDER_URI_GNOSIS=${{ secrets.PROVIDER_URI_GNOSIS }}
RUST_BACKTRACE=1 forge test -vvv
test-mac:
Expand Down Expand Up @@ -84,6 +86,8 @@ jobs:

- name: Run Foundry tests
run: |
export PROVIDER_URI_MAINNET=${{ secrets.PROVIDER_URI_MAINNET }}
export PROVIDER_URI_SEPOLIA=${{ secrets.PROVIDER_URI_SEPOLIA }}
export PROVIDER_URI_BASE=${{ secrets.PROVIDER_URI_BASE }}
export PROVIDER_URI_GNOSIS=${{ secrets.PROVIDER_URI_GNOSIS }}
RUST_BACKTRACE=1 forge test -vvv
61 changes: 52 additions & 9 deletions build/axiom-std-cli-build.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,15 @@ var require_compile = __commonJS({
var utils_12 = require("@axiom-crypto/circuit/cliHandler/utils");
var utils_22 = require_utils();
var viem_12 = require("viem");
var compile = async (circuitPath, providerUri2, options) => {
var compile = async (circuitPath, rpcUrl2, options) => {
const { restoreConsole: restoreConsole2, getCaptures: getCaptures2 } = (0, utils_22.redirectConsole)();
let circuitFunction = "circuit";
const f = await (0, utils_12.getFunctionFromTs)(circuitPath, circuitFunction);
const provider2 = (0, utils_12.getProvider)(providerUri2);
const rpcUrlOrCache2 = (0, utils_12.getRpcUrl)(rpcUrl2);
const circuit2 = new js_12.AxiomBaseCircuit({
f: f.circuit,
mock: true,
provider: provider2,
rpcUrl: rpcUrlOrCache2,
shouldTime: false,
inputSchema: f.inputSchema
});
Expand Down Expand Up @@ -217,18 +217,19 @@ var require_prove = __commonJS({
var viem_1 = require("viem");
var client_1 = require("@axiom-crypto/client");
var utils_3 = require("@axiom-crypto/client/axiom/utils");
var prove = async (compiledJson, inputs, providerUri, sourceChainId, callbackTarget, callbackExtraData, refundAddress, maxFeePerGas, callbackGasLimit, caller) => {
var address_1 = require("@axiom-crypto/client/lib/address");
var prove = async (compiledJson, inputs, rpcUrl, sourceChainId, callbackTarget, callbackExtraData, refundAddress, maxFeePerGas, callbackGasLimit, caller, targetChainId, bridgeId, broadcaster, blockhashOracle, targetRpcUrl) => {
const { restoreConsole, getCaptures } = (0, utils_2.redirectConsole)();
const decoder = new TextDecoder();
const provider = (0, utils_1.getProvider)(providerUri);
const rpcUrlOrCache = (0, utils_1.getRpcUrl)(rpcUrl);
let compiled = JSON.parse(compiledJson);
const decodedArray = Buffer.from(compiled.circuit, "base64");
const raw = decoder.decode(decodedArray);
const AXIOM_CLIENT_IMPORT = require("@axiom-crypto/client");
const circuit = new js_1.AxiomBaseCircuit({
f: eval(raw),
mock: true,
provider,
rpcUrl: rpcUrlOrCache,
shouldTime: false,
inputSchema: compiled.inputSchema
});
Expand All @@ -246,15 +247,57 @@ var require_prove = __commonJS({
computeResults,
dataQuery
};
let axiomV2QueryAddress;
if (blockhashOracle) {
if (broadcaster) {
throw new Error("Cannot use both broadcaster and blockhash oracle");
}
if (!targetChainId) {
throw new Error("`targetChainId` is required for blockhash oracle bridge type");
}
if (sourceChainId == "1" && targetChainId == "8453") {
axiomV2QueryAddress = (0, address_1.getAxiomV2QueryBlockhashOracleAddress)({ sourceChainId, targetChainId });
} else {
axiomV2QueryAddress = "0xdEaDBEefDeaDbEefDeAdbeefDeAdbEEfAAaaAAaA";
}
} else if (broadcaster) {
if (!targetChainId) {
throw new Error("`targetChainId` is required for broadcaster bridge type");
}
if (!bridgeId) {
throw new Error("`bridgeId` is required for broadcaster bridge type");
}
if (false) {
axiomV2QueryAddress = (0, address_1.getAxiomV2QueryBroadcasterAddress)({ sourceChainId, targetChainId, bridgeId });
} else {
axiomV2QueryAddress = "0xdEaDBEefDeaDbEefDeAdbeefDeAdbEEfAAaaAAaA";
}
} else {
if (sourceChainId in ["1", "11155111", "8453", "84532"]) {
axiomV2QueryAddress = (0, address_1.getAxiomV2QueryAddress)(sourceChainId);
} else {
axiomV2QueryAddress = "0xdEaDBEefDeaDbEefDeAdbeefDeAdbEEfAAaaAAaA";
}
}
let target;
if (blockhashOracle || broadcaster) {
const targetRpcUrlOrCache = (0, utils_1.getRpcUrl)(targetRpcUrl);
target = {
chainId: targetChainId,
rpcUrl: targetRpcUrlOrCache
};
}
let build = await (0, client_1.buildSendQuery)({
chainId: sourceChainId,
providerUri: provider,
rpcUrl: rpcUrlOrCache,
axiomV2QueryAddress,
dataQuery: res.dataQuery,
computeQuery: res.computeQuery,
callback: {
target: callbackTarget,
extraData: callbackExtraData
},
target,
caller,
mock: false,
options: {
Expand Down Expand Up @@ -295,6 +338,6 @@ var compile_1 = require_compile();
var prove_1 = require_prove();
var program = new commander_1.Command("axiom-std");
program.name("axiom-std").usage("axiom-std CLI");
program.command("readCircuit").description("Read and compile a circuit").argument("<circuitPath>", "path to the typescript circuit file").argument("<providerUri>", "provider to use").option("-q, --override-query-schema <suffix>", "query schema").action(compile_1.compile);
program.command("prove").description("Prove a circuit").argument("<compiledJson>", "compiled json string").argument("<inputs>", "inputs to the circuit").argument("<providerUri>", "provider to use").argument("<sourceChainId>", "source chain id").argument("<callbackTarget>", "callback target").argument("<callbackExtraData>", "callback extra data").argument("<refundAddress>", "refund address").argument("<maxFeePerGas>", "max fee per gas").argument("<callbackGasLimit>", "callback gas limit").argument("<caller>", "caller").action(prove_1.prove);
program.command("read-circuit").description("Read and compile a circuit").argument("<circuit-path>", "path to the typescript circuit file").argument("<rpc-url>", "JSON-RPC provider to use").option("-q, --override-query-schema <suffix>", "query schema").action(compile_1.compile);
program.command("prove").description("Prove a circuit and generate query results").argument("<compiled-json>", "compiled json string").argument("<inputs>", "inputs to the circuit").argument("<rpc-url>", "JSON-RPC provider to use for the source chain").argument("<source-chain-id>", "source chain id").argument("<callback-target>", "callback target").argument("<callback-extra-data>", "callback extra data").argument("<refund-address>", "refund address").argument("<max-fee-per-gas>", "max fee per gas").argument("<callback-gas-limit>", "callback gas limit").argument("<caller>", "caller").option("-t, --target-chain-id <target-chain-id>", "target chain id").option("-b, --bridge-id <bridge-id>", "bridge id", parseInt).option("-br, --broadcaster", "Use crosschain broadcaster").option("-bo, --blockhash-oracle", "Use crosschain blockhash oracle").option("-tr, --target-rpc-url <target-rpc-url>", "JSON-RPC provider to use for the target chain").action(prove_1.prove);
program.parseAsync(process.argv);
29 changes: 17 additions & 12 deletions cli/axiom-std-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,30 @@ const program = new Command("axiom-std");

program.name("axiom-std").usage("axiom-std CLI");

program.command("readCircuit")
program.command("read-circuit")
.description("Read and compile a circuit")
.argument("<circuitPath>", "path to the typescript circuit file")
.argument("<providerUri>", "provider to use")
.argument("<circuit-path>", "path to the typescript circuit file")
.argument("<rpc-url>", "JSON-RPC provider to use")
.option("-q, --override-query-schema <suffix>", "query schema")
.action(compile);

program.command("prove")
.description("Prove a circuit")
.argument("<compiledJson>", "compiled json string")
.description("Prove a circuit and generate query results")
.argument("<compiled-json>", "compiled json string")
.argument("<inputs>", "inputs to the circuit")
.argument("<providerUri>", "provider to use")
.argument("<sourceChainId>", "source chain id")
.argument("<callbackTarget>", "callback target")
.argument("<callbackExtraData>", "callback extra data")
.argument("<refundAddress>", "refund address")
.argument("<maxFeePerGas>", "max fee per gas")
.argument("<callbackGasLimit>", "callback gas limit")
.argument("<rpc-url>", "JSON-RPC provider to use for the source chain")
.argument("<source-chain-id>", "source chain id")
.argument("<callback-target>", "callback target")
.argument("<callback-extra-data>", "callback extra data")
.argument("<refund-address>", "refund address")
.argument("<max-fee-per-gas>", "max fee per gas")
.argument("<callback-gas-limit>", "callback gas limit")
.argument("<caller>", "caller")
.option("-t, --target-chain-id <target-chain-id>", "target chain id")
.option("-b, --bridge-id <bridge-id>", "bridge id", parseInt)
.option("-br, --broadcaster", "Use crosschain broadcaster")
.option("-bo, --blockhash-oracle", "Use crosschain blockhash oracle")
.option("-tr, --target-rpc-url <target-rpc-url>", "JSON-RPC provider to use for the target chain")
.action(prove);

program.parseAsync(process.argv);
8 changes: 4 additions & 4 deletions cli/compile.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { AxiomBaseCircuit } from "@axiom-crypto/circuit/js";
import { getFunctionFromTs, getProvider } from "@axiom-crypto/circuit/cliHandler/utils";
import { getFunctionFromTs, getRpcUrl } from "@axiom-crypto/circuit/cliHandler/utils";
import { redirectConsole } from "./utils";
import { encodeAbiParameters, parseAbiParameters } from "viem";

export const compile = async (
circuitPath: string,
providerUri: string,
rpcUrl: string,
options: { overrideQuerySchema?: string }
) => {
const { restoreConsole, getCaptures } = redirectConsole();
let circuitFunction = "circuit";
const f = await getFunctionFromTs(circuitPath, circuitFunction);
const provider = getProvider(providerUri);
const rpcUrlOrCache = getRpcUrl(rpcUrl);
const circuit = new AxiomBaseCircuit({
f: f.circuit,
mock: true,
provider,
rpcUrl: rpcUrlOrCache,
shouldTime: false,
inputSchema: f.inputSchema,
})
Expand Down
63 changes: 58 additions & 5 deletions cli/prove.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
import { AxiomBaseCircuit } from "@axiom-crypto/circuit/js";
import { getProvider } from "@axiom-crypto/circuit/cliHandler/utils";
import { getRpcUrl } from "@axiom-crypto/circuit/cliHandler/utils";
import { getInputs, redirectConsole } from './utils';
import { encodeAbiParameters, parseAbiParameters } from 'viem';
import { buildSendQuery } from "@axiom-crypto/client";
import { argsArrToObj } from '@axiom-crypto/client/axiom/utils';
import {
getAxiomV2QueryAddress,
getAxiomV2QueryBroadcasterAddress,
getAxiomV2QueryBlockhashOracleAddress
} from '@axiom-crypto/client/lib/address';

export const prove = async (
compiledJson: string,
inputs: string,
providerUri: string,
rpcUrl: string,
sourceChainId: string,
callbackTarget: string,
callbackExtraData: string,
refundAddress: string,
maxFeePerGas: string,
callbackGasLimit: string,
caller: string,
targetChainId?: string,
bridgeId?: number,
broadcaster?: boolean,
blockhashOracle?: boolean,
targetRpcUrl?: string,
) => {
const { restoreConsole, getCaptures } = redirectConsole();
const decoder = new TextDecoder();

const provider = getProvider(providerUri);
const rpcUrlOrCache = getRpcUrl(rpcUrl);
let compiled = JSON.parse(compiledJson);

const decodedArray = Buffer.from(compiled.circuit, 'base64');
Expand All @@ -30,7 +40,7 @@ export const prove = async (
const circuit = new AxiomBaseCircuit({
f: eval(raw),
mock: true,
provider,
rpcUrl: rpcUrlOrCache,
shouldTime: false,
inputSchema: compiled.inputSchema,
})
Expand All @@ -53,15 +63,58 @@ export const prove = async (
dataQuery,
}

let axiomV2QueryAddress;
if (blockhashOracle) {
if (broadcaster) {
throw new Error("Cannot use both broadcaster and blockhash oracle");
}
if (!targetChainId) {
throw new Error("`targetChainId` is required for blockhash oracle bridge type");
}
if (sourceChainId == "1" && targetChainId == "8453") {
axiomV2QueryAddress = getAxiomV2QueryBlockhashOracleAddress({sourceChainId, targetChainId});
} else {
axiomV2QueryAddress = "0xdEaDBEefDeaDbEefDeAdbeefDeAdbEEfAAaaAAaA";
}
} else if (broadcaster) {
if (!targetChainId) {
throw new Error("`targetChainId` is required for broadcaster bridge type");
}
if (!bridgeId) {
throw new Error("`bridgeId` is required for broadcaster bridge type");
}
if (false) {
axiomV2QueryAddress = getAxiomV2QueryBroadcasterAddress({sourceChainId, targetChainId: targetChainId!, bridgeId: bridgeId!});
} else {
axiomV2QueryAddress = "0xdEaDBEefDeaDbEefDeAdbeefDeAdbEEfAAaaAAaA";
}
} else {
if (sourceChainId in ["1", "11155111", "8453", "84532"]) {
axiomV2QueryAddress = getAxiomV2QueryAddress(sourceChainId);
} else {
axiomV2QueryAddress = "0xdEaDBEefDeaDbEefDeAdbeefDeAdbEEfAAaaAAaA";
}
}

let target;
if (blockhashOracle || broadcaster) {
const targetRpcUrlOrCache = getRpcUrl(targetRpcUrl);
target = {
chainId: targetChainId!,
rpcUrl: targetRpcUrlOrCache,
};
}
let build = await buildSendQuery({
chainId: sourceChainId,
providerUri: provider,
rpcUrl: rpcUrlOrCache,
axiomV2QueryAddress,
dataQuery: res.dataQuery,
computeQuery: res.computeQuery,
callback: {
target: callbackTarget,
extraData: callbackExtraData,
},
target,
caller: caller,
mock: false,
options: {
Expand Down
3 changes: 2 additions & 1 deletion env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
PROVIDER_URI_SEPOLIA=
PROVIDER_URI_MAINNET=
PROVIDER_URI_BASE_SEPOLIA=
PROVIDER_URI_BASE=
PROVIDER_URI_BASE=
PROVIDER_URI_GNOSIS=
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ sepolia = "${PROVIDER_URI_SEPOLIA}"
mainnet = "${PROVIDER_URI_MAINNET}"
base-sepolia = "${PROVIDER_URI_BASE_SEPOLIA}"
base = "${PROVIDER_URI_BASE}"
gnosis = "${PROVIDER_URI_GNOSIS}"

[fmt]
bracket_spacing = true
Expand Down
Loading

0 comments on commit b406ae6

Please sign in to comment.