Skip to content

Commit

Permalink
feat: add ECDSA subquery (#16)
Browse files Browse the repository at this point in the history
* feat: add ecdsa subquery

* fix: update axiom-components rep

* chore: add axiom-eth deploy key to workflow

* chore: fix cargo git

* fix: ethers version

---------

Co-authored-by: Jonathan Wang <[email protected]>
  • Loading branch information
rpalakkal and jonathanpwang committed Apr 18, 2024
1 parent 6ae55b0 commit 5cf0711
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 4 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@ on:
jobs:
axiom-sdk-rust-client:
runs-on: ubuntu-latest-64core-256ram
env:
CARGO_NET_GIT_FETCH_WITH_CLI: true
steps:
- uses: actions/checkout@v3
- name: Give GitHub Actions access to axiom-crypto/axiom-eth-working
uses: webfactory/[email protected]
with:
ssh-private-key: |
${{ secrets.AXIOM_ETH_DEPLOY_PRIVATE_KEY }}
- name: Build rust client
run: |
cargo build --verbose
Expand Down
1 change: 1 addition & 0 deletions circuit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ license.workspace = true
[dependencies]
axiom-codec = { git = "ssh://[email protected]/axiom-crypto/axiom-eth-working.git", branch = "develop" }
axiom-query = { git = "ssh://[email protected]/axiom-crypto/axiom-eth-working.git", branch = "develop" }
axiom-components = { git = "ssh://[email protected]/axiom-crypto/axiom-eth-working.git", branch = "develop" }
ethers = { version = "2.0", features = ["optimism"] }
anyhow = "1.0.75"
tokio = "1.34.0"
Expand Down
36 changes: 36 additions & 0 deletions circuit/src/subquery/ecdsa.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use anyhow::Result;
use axiom_codec::types::native::AnySubquery;
use axiom_components::{
ecdsa::{utils::verify_signature, ECDSAComponentInput, ECDSAComponentNativeInput},
utils::flatten::InputFlatten,
};
use axiom_query::axiom_eth::{halo2_base::AssignedValue, Field};
use ethers::{
providers::{JsonRpcClient, Provider},
types::H256,
};

use super::caller::FetchSubquery;

impl<F: Field> FetchSubquery<F> for ECDSAComponentInput<AssignedValue<F>> {
fn fetch<P: JsonRpcClient>(&self, _: &Provider<P>) -> Result<H256> {
let flattened_subquery = self.flatten();
let subquery_value: Vec<F> = flattened_subquery.iter().map(|v| *v.value()).collect();
let unflattened_subquery = ECDSAComponentInput::unflatten(subquery_value).unwrap();
let native_input: ECDSAComponentNativeInput = unflattened_subquery.into();
let res = verify_signature(native_input)?;
Ok(H256::from_low_u64_be(res as u64))
}

fn any_subquery(&self) -> AnySubquery {
let flattened_subquery = self.flatten();
let subquery_value: Vec<F> = flattened_subquery.iter().map(|v| *v.value()).collect();
let unflattened_subquery = ECDSAComponentInput::unflatten(subquery_value).unwrap();
let native_input: ECDSAComponentNativeInput = unflattened_subquery.into();
AnySubquery::ECDSA(native_input)
}

fn flatten(&self) -> Vec<AssignedValue<F>> {
self.flatten_vec()
}
}
1 change: 1 addition & 0 deletions circuit/src/subquery/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub(crate) mod account;
pub(crate) mod ecdsa;
pub(crate) mod header;
pub(crate) mod mapping;
pub(crate) mod receipt;
Expand Down
2 changes: 2 additions & 0 deletions circuit/src/subquery/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use axiom_codec::{
utils::native::{decode_field_to_addr, decode_hilo_to_h256},
HiLo,
};
pub use axiom_components::ecdsa::ECDSAComponentInput;
use axiom_query::axiom_eth::{halo2_base::AssignedValue, Field};
use ethers::types::{BigEndianHash, H256};
use serde::{Serialize, Serializer};
Expand Down Expand Up @@ -161,6 +162,7 @@ impl Serialize for RawSubquery {
AnySubquery::Transaction(ref inner) => inner.serialize(serializer),
AnySubquery::Receipt(ref inner) => inner.serialize(serializer),
AnySubquery::SolidityNestedMapping(ref inner) => inner.serialize(serializer),
AnySubquery::ECDSA(ref inner) => inner.serialize(serializer),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions circuit/src/subquery/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub fn get_subquery_type_from_any_subquery(any_subquery: &AnySubquery) -> u64 {
AnySubquery::Receipt(_) => SubqueryType::Receipt,
AnySubquery::Transaction(_) => SubqueryType::Transaction,
AnySubquery::SolidityNestedMapping(_) => SubqueryType::SolidityNestedMapping,
AnySubquery::ECDSA(_) => SubqueryType::ECDSA,
};
subquery_type as u64
}
7 changes: 6 additions & 1 deletion circuit/src/tests/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ use test_case::test_case;

use super::{
shared_tests::check_compute_proof_and_query_format,
utils::{all_subqueries_call, header_call, mapping_call, receipt_call, storage_call, tx_call},
utils::{
all_subqueries_call, ecdsa_call, header_call, mapping_call, receipt_call, storage_call,
tx_call,
},
};
use crate::{
scaffold::{AxiomCircuit, AxiomCircuitScaffold},
Expand Down Expand Up @@ -67,6 +70,7 @@ base_test_struct!(StorageTest, storage_call);
base_test_struct!(MappingTest, mapping_call);
base_test_struct!(TxTest, tx_call);
base_test_struct!(AllSubqueryTest, all_subqueries_call);
base_test_struct!(EcdsaTest, ecdsa_call);

// #[test_case(AccountTest)]
// #[test_case(HeaderTest)]
Expand All @@ -86,6 +90,7 @@ pub fn mock<S: AxiomCircuitScaffold<Http, Fr>>(_circuit: S) {
#[test_case(StorageTest)]
#[test_case(MappingTest)]
#[test_case(TxTest)]
#[test_case(EcdsaTest)]
pub fn test_single_subquery_instances<S: AxiomCircuitScaffold<Http, Fr>>(_circuit: S) {
let params = get_base_test_params();
let client = get_provider();
Expand Down
4 changes: 3 additions & 1 deletion circuit/src/tests/keccak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use test_case::test_case;

use super::{
shared_tests::{check_compute_proof_format, check_compute_query_format, single_instance_test},
utils::{all_subqueries_call, mapping_call, receipt_call, storage_call, tx_call},
utils::{all_subqueries_call, ecdsa_call, mapping_call, receipt_call, storage_call, tx_call},
};
use crate::{
aggregation::create_aggregation_circuit,
Expand Down Expand Up @@ -107,6 +107,7 @@ keccak_test_struct!(StorageTest, storage_call);
keccak_test_struct!(MappingTest, mapping_call);
keccak_test_struct!(TxTest, tx_call);
keccak_test_struct!(AllSubqueryTest, all_subqueries_call);
keccak_test_struct!(ECDSATest, ecdsa_call);

// #[test_case(AccountTest)]
// #[test_case(HeaderTest)]
Expand All @@ -130,6 +131,7 @@ pub fn mock<S: AxiomCircuitScaffold<Http, Fr>>(_circuit: S) {
#[test_case(StorageTest)]
#[test_case(MappingTest)]
#[test_case(TxTest)]
#[test_case(ECDSATest)]
pub fn test_single_subquery_instances<S: AxiomCircuitScaffold<Http, Fr>>(_circuit: S) {
let params = get_keccak_test_params();
let agg_circuit_params = get_agg_test_params();
Expand Down
5 changes: 4 additions & 1 deletion circuit/src/tests/rlc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use test_case::test_case;

use super::{
shared_tests::check_compute_proof_and_query_format,
utils::{all_subqueries_call, mapping_call, receipt_call, storage_call, tx_call},
utils::{all_subqueries_call, ecdsa_call, mapping_call, receipt_call, storage_call, tx_call},
};
use crate::{
scaffold::{AxiomCircuit, AxiomCircuitScaffold},
Expand Down Expand Up @@ -70,6 +70,7 @@ rlc_test_struct!(ReceiptTest, receipt_call);
rlc_test_struct!(StorageTest, storage_call);
rlc_test_struct!(MappingTest, mapping_call);
rlc_test_struct!(TxTest, tx_call);
rlc_test_struct!(ECDSATest, ecdsa_call);
rlc_test_struct!(AllSubqueryTest, all_subqueries_call);

#[test_case(AccountTest)]
Expand All @@ -78,6 +79,7 @@ rlc_test_struct!(AllSubqueryTest, all_subqueries_call);
#[test_case(StorageTest)]
#[test_case(MappingTest)]
#[test_case(TxTest)]
#[test_case(ECDSATest)]
#[test_case(AllSubqueryTest)]
pub fn mock<S: AxiomCircuitScaffold<Http, Fr>>(_circuit: S) {
let params = get_rlc_test_params();
Expand All @@ -90,6 +92,7 @@ pub fn mock<S: AxiomCircuitScaffold<Http, Fr>>(_circuit: S) {
#[test_case(StorageTest)]
#[test_case(MappingTest)]
#[test_case(TxTest)]
#[test_case(ECDSATest)]
pub fn test_single_subquery_instances<S: AxiomCircuitScaffold<Http, Fr>>(_circuit: S) {
let params = get_rlc_test_params();
let client = get_provider();
Expand Down
20 changes: 20 additions & 0 deletions circuit/src/tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ use std::{
};

use axiom_codec::{constants::MAX_SOLIDITY_MAPPING_KEYS, HiLo};
use axiom_components::{
ecdsa::{utils::testing::custom_parameters_ecdsa, ECDSAComponentInput},
framework::types::FixLenLogical,
};
use axiom_query::axiom_eth::{
halo2_base::AssignedValue, halo2curves::bn256::Fr, rlc::circuit::builder::RlcCircuitBuilder,
utils::encode_addr_to_field,
Expand Down Expand Up @@ -169,6 +173,21 @@ pub fn tx_call<P: JsonRpcClient>(
val
}

pub fn ecdsa_call<P: JsonRpcClient>(
builder: &mut RlcCircuitBuilder<Fr>,
subquery_caller: Arc<Mutex<SubqueryCaller<P, Fr>>>,
) -> HiLo<AssignedValue<Fr>> {
let raw_subquery = custom_parameters_ecdsa(1, 1, 1);
let flattened_subquery = raw_subquery.flatten();
let assigned_subquery = builder.base.main(0).assign_witnesses(flattened_subquery);
let subquery = ECDSAComponentInput::try_from_raw(assigned_subquery).unwrap();
let val = subquery_caller
.lock()
.unwrap()
.call(ctx!(builder, 0), subquery);
val
}

pub fn all_subqueries_call<P: JsonRpcClient>(
builder: &mut RlcCircuitBuilder<Fr>,
subquery_caller: Arc<Mutex<SubqueryCaller<P, Fr>>>,
Expand All @@ -180,6 +199,7 @@ pub fn all_subqueries_call<P: JsonRpcClient>(
receipt_call(builder, subquery_caller.clone()),
storage_call(builder, subquery_caller.clone()),
tx_call(builder, subquery_caller.clone()),
ecdsa_call(builder, subquery_caller.clone()),
];
vals
}
23 changes: 22 additions & 1 deletion sdk/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use axiom_circuit::{
rlc::circuit::builder::RlcCircuitBuilder,
utils::uint_to_bytes_be,
},
subquery::caller::SubqueryCaller,
subquery::{caller::SubqueryCaller, types::ECDSAComponentInput},
utils::{from_hi_lo, to_hi_lo},
};
use ethers::providers::Http;
Expand Down Expand Up @@ -172,6 +172,27 @@ impl<'a> AxiomAPI<'a> {
get_tx(ctx, self.subquery_caller.clone(), block_number, tx_idx)
}

pub fn ecdsa_sig_verify(
&mut self,
pubkey: (HiLo<AssignedValue<Fr>>, HiLo<AssignedValue<Fr>>),
r: HiLo<AssignedValue<Fr>>,
s: HiLo<AssignedValue<Fr>>,
msg_hash: HiLo<AssignedValue<Fr>>,
) -> HiLo<AssignedValue<Fr>> {
let ctx = self.builder.base.main(0);
let subquery_caller = self.subquery_caller.clone();
let mut subquery_caller = subquery_caller.lock().unwrap();

let input = ECDSAComponentInput {
pubkey,
r,
s,
msg_hash,
};

subquery_caller.call(ctx, input)
}

pub fn keccak_fix_len(&mut self, bytes: Vec<AssignedValue<Fr>>) -> HiLo<AssignedValue<Fr>> {
let ctx = self.builder.base.main(0);
let subquery_caller = self.subquery_caller.clone();
Expand Down

0 comments on commit 5cf0711

Please sign in to comment.