From 9a4382ed22bd00bce3fd4133b614899254ac36e0 Mon Sep 17 00:00:00 2001 From: Tarrence van As Date: Mon, 18 Mar 2024 11:09:42 -0400 Subject: [PATCH] Add CI --- .github/workflows/ci.yml | 69 +++++++++++++++++++ .gitignore | 2 + .tool-versions | 2 - README.md | 2 +- Scarb.toml | 6 +- crates/account_sdk/src/felt_ser.rs | 3 +- .../account_sdk/src/tests/deployment_test.rs | 21 +++--- crates/account_sdk/src/tests/session/uitls.rs | 8 +-- crates/cartridge_account/src/lib.cairo | 2 +- .../auth/src/deserializable_endpoints.cairo | 6 +- crates/webauthn/session/src/lib.cairo | 3 - crates/webauthn/session/src/signature.cairo | 30 ++++++++ crates/webauthn/session/src/tests.cairo | 3 - .../src/tests/signature_deserialization.cairo | 27 -------- crates/webauthn/tests/src/arg_builder.rs | 6 ++ .../tests/src/auth/expand_auth_data.rs | 2 +- .../tests/src/auth/verify_signature.rs | 27 ++++---- crates/webauthn/tests/src/prop_utils.rs | 2 +- .../src/session/prop_signature_proofs.rs | 2 +- crates/webauthn/tests/src/utils.rs | 4 +- 20 files changed, 147 insertions(+), 80 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 crates/webauthn/session/src/tests.cairo delete mode 100644 crates/webauthn/session/src/tests/signature_deserialization.cairo diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..4ccac4be --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,69 @@ +name: ci + +on: + push: + branches: + - main + pull_request: + +env: + CARGO_TERM_COLOR: always + RUST_VERSION: nightly-2023-09-26 + +jobs: + test: + runs-on: ubuntu-latest + container: + image: ghcr.io/dojoengine/dojo-dev:5d61184 + steps: + - uses: actions/checkout@v3 + - uses: asdf-vm/actions/install@v3 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: ${{ env.RUST_VERSION }} + components: llvm-tools-preview + - uses: taiki-e/install-action@cargo-llvm-cov + - run: cargo llvm-cov --all-features --lcov --output-path lcov.info + - uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: lcov.info + + ensure-wasm: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: ${{ env.RUST_VERSION }} + target: wasm32-unknown-unknown + - run: cargo build -r --target wasm32-unknown-unknown -p account-sdk + + cairo-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: asdf-vm/actions/install@v3 + - run: scarb fmt --check + - run: snforge test + + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: asdf-vm/actions/install@v3 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: ${{ env.RUST_VERSION }} + components: clippy + - run: cargo clippy --all-targets --all-features + + fmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: ${{ env.RUST_VERSION }} + components: rustfmt + - uses: actions-rust-lang/rustfmt@v1 diff --git a/.gitignore b/.gitignore index d770d50d..230cd553 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,5 @@ Cargo.lock # Logs **/log/ + +lcov.info diff --git a/.tool-versions b/.tool-versions index f0fa06cc..537bae24 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,4 +1,2 @@ scarb 2.5.4 starknet-foundry 0.18.0 -python 3.9.18 -dojo 0.4.4 \ No newline at end of file diff --git a/README.md b/README.md index bd990e09..f4473106 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ cargo build -p account-sdk --target wasm32-unknown-unknown --release Note, that to run the tests you first have to [compile](#compiling-the-cairo-code) (to sierra and casm) the contract in the `cartidge_account` folder. -StarkNet Foundry tests: +Starknet Foundry tests: ```bash snforge test -p cartridge_account diff --git a/Scarb.toml b/Scarb.toml index de97dcee..9fbd56e6 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -10,9 +10,9 @@ edition = "2023_10" version = "0.1.0" [workspace.dependencies] -alexandria_data_structures = { git = "https://github.com/keep-starknet-strange/alexandria", tag="cairo-v2.5.4" } -alexandria_encoding = { git = "https://github.com/keep-starknet-strange/alexandria", tag="cairo-v2.5.4" } -alexandria_merkle_tree = { git = "https://github.com/keep-starknet-strange/alexandria", tag="cairo-v2.5.4" } +alexandria_data_structures = { git = "https://github.com/keep-starknet-strange/alexandria", tag = "cairo-v2.5.4" } +alexandria_encoding = { git = "https://github.com/keep-starknet-strange/alexandria", tag = "cairo-v2.5.4" } +alexandria_merkle_tree = { git = "https://github.com/keep-starknet-strange/alexandria", tag = "cairo-v2.5.4" } openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts", tag = "v0.9.0" } snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.18.0" } starknet = "2.5.3" diff --git a/crates/account_sdk/src/felt_ser.rs b/crates/account_sdk/src/felt_ser.rs index 43b46205..0ef4ec98 100644 --- a/crates/account_sdk/src/felt_ser.rs +++ b/crates/account_sdk/src/felt_ser.rs @@ -395,8 +395,7 @@ mod tests { let serialized = vec![val.a, val.i.into(), val.x.into()]; let seq = (0..100).map(|_| val.clone()).collect::>(); let mut result = (0..100) - .map(|_| serialized.clone()) - .flatten() + .flat_map(|_| serialized.clone()) .collect::>(); result.insert(0, seq.len().into()); assert_eq!(to_felts(&seq), result); diff --git a/crates/account_sdk/src/tests/deployment_test.rs b/crates/account_sdk/src/tests/deployment_test.rs index 24b96523..c240074b 100644 --- a/crates/account_sdk/src/tests/deployment_test.rs +++ b/crates/account_sdk/src/tests/deployment_test.rs @@ -20,11 +20,11 @@ pub async fn create_account<'a>( SigningKey, ) { let provider = *from.provider(); - let class_hash = declare(provider, &from).await; + let class_hash = declare(provider, from).await; let private_key = SigningKey::from_random(); let deployed_address = deploy( provider, - &from, + from, private_key.verifying_key().scalar(), class_hash, ) @@ -53,13 +53,12 @@ pub async fn declare( client: &JsonRpcClient, account: &SingleOwnerAccount<&JsonRpcClient, LocalWallet>, ) -> FieldElement { - let DeclareTransactionResult { class_hash, .. } = - AccountDeclaration::cartridge_account(&client) - .declare(&account) - .await - .unwrap() - .wait_for_completion() - .await; + let DeclareTransactionResult { class_hash, .. } = AccountDeclaration::cartridge_account(client) + .declare(account) + .await + .unwrap() + .wait_for_completion() + .await; class_hash } @@ -72,8 +71,8 @@ pub async fn deploy( ) -> FieldElement { let DeployResult { deployed_address, .. - } = AccountDeployment::new(&client) - .deploy(vec![public_key], FieldElement::ZERO, &account, class_hash) + } = AccountDeployment::new(client) + .deploy(vec![public_key], FieldElement::ZERO, account, class_hash) .await .unwrap() .wait_for_completion() diff --git a/crates/account_sdk/src/tests/session/uitls.rs b/crates/account_sdk/src/tests/session/uitls.rs index 40fb8eba..aacb896c 100644 --- a/crates/account_sdk/src/tests/session/uitls.rs +++ b/crates/account_sdk/src/tests/session/uitls.rs @@ -12,12 +12,12 @@ use crate::{abigen::account::Call, tests::runners::TestnetRunner}; use crate::session_token::Session; -pub async fn create_session_account<'a, T>( - runner: &'a T, +pub async fn create_session_account( + runner: &T, ) -> ( - SessionAccount<&'a JsonRpcClient, LocalWallet>, + SessionAccount<&JsonRpcClient, LocalWallet>, SigningKey, - SingleOwnerAccount<&'a JsonRpcClient, LocalWallet>, + SingleOwnerAccount<&JsonRpcClient, LocalWallet>, ) where T: TestnetRunner, diff --git a/crates/cartridge_account/src/lib.cairo b/crates/cartridge_account/src/lib.cairo index 5247d258..aa668c08 100644 --- a/crates/cartridge_account/src/lib.cairo +++ b/crates/cartridge_account/src/lib.cairo @@ -240,7 +240,7 @@ mod Account { } fn _execute_single_call(call: Call) -> Span { - let Call{to, selector, calldata } = call; + let Call { to, selector, calldata } = call; starknet::call_contract_syscall(to, selector, calldata).unwrap() } } diff --git a/crates/webauthn/auth/src/deserializable_endpoints.cairo b/crates/webauthn/auth/src/deserializable_endpoints.cairo index 640b3e11..2dede7ce 100644 --- a/crates/webauthn/auth/src/deserializable_endpoints.cairo +++ b/crates/webauthn/auth/src/deserializable_endpoints.cairo @@ -18,13 +18,11 @@ fn verify_hashed_ecdsa_endpoint( verify_hashed_ecdsa(pub_key_point, msg_hash, r, s) } -fn expand_auth_data_endpoint( - auth_data: Array -) -> AuthenticatorData { +fn expand_auth_data_endpoint(auth_data: Array) -> AuthenticatorData { let data: Option = ImplArrayu8TryIntoAuthData::try_into(auth_data); return data.unwrap(); } fn extract_u256_from_u8_array_endpoint(bytes: Array, offset: u32) -> Option { extract_u256_from_u8_array(@bytes, offset) -} \ No newline at end of file +} diff --git a/crates/webauthn/session/src/lib.cairo b/crates/webauthn/session/src/lib.cairo index 9be137ef..0910a45f 100644 --- a/crates/webauthn/session/src/lib.cairo +++ b/crates/webauthn/session/src/lib.cairo @@ -22,9 +22,6 @@ mod signature; mod interface; mod deserializable_endpoints; -#[cfg(test)] -mod tests; - const SESSION_TOKEN_V1: felt252 = 'Session Token v1'; // Based on https://github.com/argentlabs/starknet-plugin-account/blob/3c14770c3f7734ef208536d91bbd76af56dc2043/contracts/plugins/SessionKey.cairo diff --git a/crates/webauthn/session/src/signature.cairo b/crates/webauthn/session/src/signature.cairo index 0073e5d8..950f4b7c 100644 --- a/crates/webauthn/session/src/signature.cairo +++ b/crates/webauthn/session/src/signature.cairo @@ -42,3 +42,33 @@ impl ImplSignatureProofs of SignatureProofsTrait { self.proofs_flat.slice(index * self.single_proof_len, self.single_proof_len) } } + +#[cfg(test)] +mod tests { + use alexandria_data_structures::array_ext::ArrayTraitExt; + use alexandria_merkle_tree::merkle_tree::{ + Hasher, MerkleTree, pedersen::PedersenHasherImpl, MerkleTreeTrait + }; + use core::box::BoxTrait; + use core::array::SpanTrait; + use core::{TryInto, Into}; + use core::ecdsa::check_ecdsa_signature; + use starknet::info::{TxInfo, get_tx_info, get_block_timestamp}; + use starknet::{contract_address::ContractAddress}; + use webauthn_session::hash::{compute_session_hash, compute_call_hash}; + + use super::{SessionSignature, SignatureProofs, SignatureProofsTrait}; + + #[test] + #[available_gas(200000000000)] + fn test_session_deserialize() { + let mut sig = array![ + 0x1, 0x42, 0x43, 0x69, 18446744073709551615, 0x0, 0x1, 0x1, 0x44, 0x1, 0x2137, + ] + .span(); + + let deser: SessionSignature = Serde::::deserialize(ref sig).unwrap(); + assert(deser.r == 0x42, 'invalid r'); + assert(deser.proofs.len() == 1, 'invalid proofs len'); + } +} diff --git a/crates/webauthn/session/src/tests.cairo b/crates/webauthn/session/src/tests.cairo deleted file mode 100644 index 0ff6179a..00000000 --- a/crates/webauthn/session/src/tests.cairo +++ /dev/null @@ -1,3 +0,0 @@ -mod signature_deserialization; - - diff --git a/crates/webauthn/session/src/tests/signature_deserialization.cairo b/crates/webauthn/session/src/tests/signature_deserialization.cairo deleted file mode 100644 index f5ce63e6..00000000 --- a/crates/webauthn/session/src/tests/signature_deserialization.cairo +++ /dev/null @@ -1,27 +0,0 @@ -use webauthn_session::signature::SignatureProofsTrait; -use alexandria_data_structures::array_ext::ArrayTraitExt; -use core::box::BoxTrait; -use core::array::SpanTrait; -use starknet::info::{TxInfo, get_tx_info, get_block_timestamp}; -use core::{TryInto, Into}; -use starknet::{contract_address::ContractAddress}; -use webauthn_session::signature::{SessionSignature, SignatureProofs}; -use webauthn_session::hash::{compute_session_hash, compute_call_hash}; -use alexandria_merkle_tree::merkle_tree::{ - Hasher, MerkleTree, pedersen::PedersenHasherImpl, MerkleTreeTrait -}; - - -use core::ecdsa::check_ecdsa_signature; - - -#[test] -#[available_gas(200000000000)] -fn test_session() { - let mut sig = array![0x42, 0x43, 0x69, 18446744073709551615, 0x0, 0x1, 0x1, 0x44, 0x1, 0x2137,] - .span(); - - let deser: SessionSignature = Serde::::deserialize(ref sig).unwrap(); - assert(deser.r == 0x42, 'invalid r'); - assert(deser.proofs.len() == 1, 'invalid proofs len'); -} diff --git a/crates/webauthn/tests/src/arg_builder.rs b/crates/webauthn/tests/src/arg_builder.rs index b24800bf..8c11616f 100644 --- a/crates/webauthn/tests/src/arg_builder.rs +++ b/crates/webauthn/tests/src/arg_builder.rs @@ -29,6 +29,12 @@ impl ArgsBuilder { } } +impl Default for ArgsBuilder { + fn default() -> Self { + Self::new() + } +} + pub trait FeltSerialize { fn to_felts(self) -> Vec; } diff --git a/crates/webauthn/tests/src/auth/expand_auth_data.rs b/crates/webauthn/tests/src/auth/expand_auth_data.rs index bdab39ff..eb46fe9a 100644 --- a/crates/webauthn/tests/src/auth/expand_auth_data.rs +++ b/crates/webauthn/tests/src/auth/expand_auth_data.rs @@ -91,7 +91,7 @@ impl FeltSerialize for AuthenticatorData { #[test] fn test_expand_auth_data_1() { - let d: Vec = (0_u8..32_u8).into_iter().collect(); + let d: Vec = (0_u8..32_u8).collect(); let auth_data = AuthenticatorData { rp_id_hash: d.try_into().unwrap(), flags: 0, diff --git a/crates/webauthn/tests/src/auth/verify_signature.rs b/crates/webauthn/tests/src/auth/verify_signature.rs index 184ed1f1..2645a81c 100644 --- a/crates/webauthn/tests/src/auth/verify_signature.rs +++ b/crates/webauthn/tests/src/auth/verify_signature.rs @@ -29,7 +29,7 @@ fn verify_signature( .add_array(hash.iter().cloned()) .add_array(auth_data.iter().cloned()) .add_struct(pub_key.to_felts()) - .add_array(r.into_iter().copied().chain(s.iter().copied())); + .add_array(r.iter().copied().chain(s.iter().copied())); let result: [Felt252; 2] = VERIFY_SIGNATURE.run(args.build()); result == [0.into(), 0.into()] } @@ -39,7 +39,7 @@ fn test_verify_signature_1() { let hash: &[u8] = b"hello world"; let auth_data = b"dummy auth data"; let signing_key = SigningKey::random(&mut OsRng); - let (signature, _) = signing_key.sign(&vec![auth_data, hash].concat()); + let (signature, _) = signing_key.sign(&[auth_data, hash].concat()); assert!(verify_signature(hash, auth_data, signing_key, signature)) } @@ -48,7 +48,7 @@ fn test_verify_signature_2() { let hash: &[u8] = b"1234567890987654321"; let auth_data = b"auuuuuuuuuuth daaaaataaaaaaaaaa"; let signing_key = SigningKey::random(&mut OsRng); - let (signature, _) = signing_key.sign(&vec![auth_data, hash].concat()); + let (signature, _) = signing_key.sign(&[auth_data, hash].concat()); assert!(verify_signature(hash, auth_data, signing_key, signature)) } @@ -58,11 +58,8 @@ fn test_verify_signature_should_fail_1() { let auth_data = b"dummy auth data"; let wrong_hash: &[u8] = b"definetly not hello world"; let signing_key = SigningKey::random(&mut OsRng); - let (signature, _) = signing_key.sign(&vec![auth_data, wrong_hash].concat()); - assert_eq!( - verify_signature(hash, auth_data, signing_key, signature), - false - ) + let (signature, _) = signing_key.sign(&[auth_data, wrong_hash].concat()); + assert!(!verify_signature(hash, auth_data, signing_key, signature),) } #[test] @@ -71,11 +68,13 @@ fn test_verify_signature_should_fail_2() { let auth_data = b"dummy auth data"; let signing_key = SigningKey::random(&mut OsRng); let other_signing_key = SigningKey::random(&mut OsRng); - let (signature, _) = signing_key.sign(&vec![auth_data, hash].concat()); - assert_eq!( - verify_signature(hash, auth_data, other_signing_key, signature), - false - ) + let (signature, _) = signing_key.sign(&[auth_data, hash].concat()); + assert!(!verify_signature( + hash, + auth_data, + other_signing_key, + signature + )) } proptest! { @@ -90,7 +89,7 @@ proptest! { .prop_map(|b| SigningKey::from(SecretKey::from_bytes(&b.into()).unwrap())) ), ) { - let (signature, _) = signing_key.sign(&vec![auth_data.clone(), hash.clone()].concat()); + let (signature, _) = signing_key.sign(&[auth_data.clone(), hash.clone()].concat()); assert!(verify_signature(&hash, &auth_data, signing_key, signature)) } } diff --git a/crates/webauthn/tests/src/prop_utils.rs b/crates/webauthn/tests/src/prop_utils.rs index abe182e0..0ff6a436 100644 --- a/crates/webauthn/tests/src/prop_utils.rs +++ b/crates/webauthn/tests/src/prop_utils.rs @@ -5,7 +5,7 @@ use proptest::prelude::*; pub struct Felt252Strategy; impl Felt252Strategy { - pub fn new() -> impl Strategy { + pub fn new_strategy() -> impl Strategy { prop::collection::vec(any::(), 32..=32).prop_map(|b| Felt252::from_bytes_be(&b)) } } diff --git a/crates/webauthn/tests/src/session/prop_signature_proofs.rs b/crates/webauthn/tests/src/session/prop_signature_proofs.rs index 021265be..95507b56 100644 --- a/crates/webauthn/tests/src/session/prop_signature_proofs.rs +++ b/crates/webauthn/tests/src/session/prop_signature_proofs.rs @@ -11,7 +11,7 @@ fn vec_vec_felt252_strategy( ) -> impl Strategy>, usize)> { ( prop::collection::vec( - prop::collection::vec(Felt252Strategy::new(), inner_len..=inner_len), + prop::collection::vec(Felt252Strategy::new_strategy(), inner_len..=inner_len), outer_len..=outer_len, ), Just(inner_len), diff --git a/crates/webauthn/tests/src/utils.rs b/crates/webauthn/tests/src/utils.rs index bb6c4f25..e5e70241 100644 --- a/crates/webauthn/tests/src/utils.rs +++ b/crates/webauthn/tests/src/utils.rs @@ -4,8 +4,8 @@ use cairo_args_runner::errors::SierraRunnerError; use cairo_args_runner::SuccessfulRun; use cairo_args_runner::{Arg, Felt252}; -pub const WEBAUTHN_SIERRA_TARGET: &'static str = "../../../target/dev/webauthn_auth.sierra.json"; -pub const SESSION_SIERRA_TARGET: &'static str = "../../../target/dev/webauthn_session.sierra.json"; +pub const WEBAUTHN_SIERRA_TARGET: &str = "../../../target/dev/webauthn_auth.sierra.json"; +pub const SESSION_SIERRA_TARGET: &str = "../../../target/dev/webauthn_session.sierra.json"; #[derive(Debug, Clone, Copy)] pub struct Function<'a, AP, RE>