Skip to content

Commit

Permalink
Implement wildcard sessions
Browse files Browse the repository at this point in the history
  • Loading branch information
tarrencev committed Jan 9, 2025
1 parent 9294abd commit 689a7cd
Show file tree
Hide file tree
Showing 9 changed files with 18,560 additions and 18,424 deletions.

Large diffs are not rendered by default.

36,834 changes: 18,422 additions & 18,412 deletions packages/account_sdk/artifacts/classes/controller.latest.contract_class.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/account_sdk/artifacts/metadata.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"controllers": {
"latest": {
"casm_hash": "0x2f2386cd9bea7724f79d8c392b6b99228721d1e8769b1b482287520dfc4d3eb",
"class_hash": "0x511dd75da368f5311134dee2356356ac4da1538d2ad18aa66d57c47e3757d59"
"casm_hash": "0x2fcd4b347622fd2dbe973ad873666f8925b3f244120793014248b4fd9670bd9",
"class_hash": "0x743c83c41ce99ad470aa308823f417b2141e02e04571f5c0004e743556e7faf"
},
"v1.0.4": {
"casm_hash": "0x6b22de13b878ab346fa53442adaa8a40a6bd25732aa1aeb2a26375987f0be00",
Expand Down
14 changes: 12 additions & 2 deletions packages/account_sdk/src/account/session/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ impl SessionAccount {
.await
}

async fn sign(&self, hash: Felt, policies: &[Policy]) -> Result<SessionToken, SignError> {
let hash = self.message_hash(hash)?;
fn generate_proofs(&self, policies: &[Policy]) -> Result<Vec<Vec<Felt>>, SignError> {
let mut proofs = Vec::new();

for policy in policies {
Expand All @@ -113,6 +112,17 @@ impl SessionAccount {
proofs.push(proof);
}

Ok(proofs)
}

async fn sign(&self, hash: Felt, policies: &[Policy]) -> Result<SessionToken, SignError> {
let hash = self.message_hash(hash)?;
let proofs = if self.session.is_wildcard() {
vec![]
} else {
self.generate_proofs(policies)?
};

Ok(SessionToken {
session: self.session.clone().into(),
cache_authorization: true,
Expand Down
37 changes: 35 additions & 2 deletions packages/account_sdk/src/account/session/hash.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use cainome_cairo_serde::NonZero;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use serde::Serialize;
use serde_json::json;
use starknet::core::types::Felt;
use starknet::core::utils::NonAsciiNameError;
Expand Down Expand Up @@ -78,6 +79,34 @@ impl Session {
})
}

pub fn new_wildcard(
policies: Vec<Policy>,
expires_at: u64,
session_signer: &Signer,
guardian_guid: Felt,
) -> Result<Self, SignError> {
let metadata = json!({ "metadata": "metadata", "max_fee": 0 });

Ok(Self {
inner: crate::abigen::controller::Session {
expires_at,
allowed_policies_root: short_string!("wildcard-policy"),
session_key_guid: session_signer.clone().into(),
guardian_key_guid: guardian_guid,
metadata_hash: Felt::ZERO,
},
requested_policies: policies.clone(),
proved_policies: policies
.into_iter()
.map(|policy| ProvedPolicy {
policy: policy.clone(),
proof: vec![],
})
.collect(),
metadata: serde_json::to_string(&metadata).unwrap(),
})
}

pub fn message_hash(
&self,
tx_hash: Felt,
Expand All @@ -94,6 +123,10 @@ impl Session {
.map(|ProvedPolicy { proof, .. }| proof.clone())
}

pub fn is_wildcard(&self) -> bool {
self.inner.allowed_policies_root == short_string!("wildcard-policy")
}

pub fn is_authorized(&self, policy: &Policy) -> bool {
self.proved_policies.iter().any(|proved_policy| {
proved_policy.policy == *policy && proved_policy.policy.is_authorized()
Expand All @@ -107,7 +140,7 @@ impl Session {

pub fn is_session_key(&self, public_key: Felt) -> bool {
let pubkey = VerifyingKey::from_scalar(public_key);
let session_key_guid = Signer::Starknet(StarknetSigner {
let session_key_guid = abigen::controller::Signer::Starknet(StarknetSigner {
pubkey: NonZero::new(pubkey.scalar()).unwrap(),
})
.into();
Expand Down
4 changes: 2 additions & 2 deletions packages/account_sdk/src/artifacts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ lazy_static! {
Version::LATEST,
ContractClass {
content: include_str!("../artifacts/classes/controller.latest.contract_class.json"),
hash: felt!("0x511dd75da368f5311134dee2356356ac4da1538d2ad18aa66d57c47e3757d59"),
hash: felt!("0x743c83c41ce99ad470aa308823f417b2141e02e04571f5c0004e743556e7faf"),
casm_hash: felt!(
"0x2f2386cd9bea7724f79d8c392b6b99228721d1e8769b1b482287520dfc4d3eb"
"0x2fcd4b347622fd2dbe973ad873666f8925b3f244120793014248b4fd9670bd9"
),
},
);
Expand Down
31 changes: 29 additions & 2 deletions packages/account_sdk/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,33 @@ impl Controller {
&session_signer.clone().into(),
guardian,
)?;

self.create_with_session(signer, session).await
}

pub async fn create_wildcard_session(
&mut self,
methods: Vec<Policy>,
expires_at: u64,
) -> Result<SessionAccount, ControllerError> {
let signer = SigningKey::from_random();
let session_signer = Signer::Starknet(signer.clone());

let session = Session::new_wildcard(
methods,
expires_at,
&session_signer.clone().into(),
Felt::ZERO,
)?;

self.create_with_session(signer, session).await
}

pub async fn create_with_session(
&mut self,
session_signer: SigningKey,
session: Session,
) -> Result<SessionAccount, ControllerError> {
let hash = session
.inner
.get_message_hash_rev_1(self.chain_id, self.address);
Expand All @@ -55,15 +82,15 @@ impl Controller {
max_fee: None,
credentials: Some(Credentials {
authorization: authorization.clone(),
private_key: signer.secret_scalar(),
private_key: session_signer.secret_scalar(),
}),
is_registered: false,
},
)?;

let session_account = SessionAccount::new(
self.provider().clone(),
session_signer,
Signer::Starknet(session_signer),
self.address,
self.chain_id,
authorization,
Expand Down
50 changes: 50 additions & 0 deletions packages/account_sdk/src/session_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,3 +386,53 @@ pub async fn test_verify_execute_with_invalid_guardian() {
"Should return error"
);
}

#[tokio::test]
async fn test_verify_execute_session_wildcard() {
let signer = Signer::new_starknet_random();
let runner = KatanaRunner::load();
let mut controller = runner
.deploy_controller(
"username".to_owned(),
Owner::Signer(signer),
Version::LATEST,
)
.await;

let signer = SigningKey::from_random();
let session_signer = Signer::Starknet(signer.clone());
let session =
Session::new_wildcard(vec![], u64::MAX, &session_signer.into(), Felt::ZERO).unwrap();

let session_account = controller
.create_with_session(signer, session)
.await
.unwrap();

let recipient = ContractAddress(felt!("0x18301129"));
let contract_erc20 = Erc20::new(*FEE_TOKEN_ADDRESS, &session_account);

contract_erc20
.balanceOf(&recipient)
.block_id(BlockId::Tag(BlockTag::Latest))
.call()
.await
.expect("failed to call contract");

let tx = contract_erc20
.transfer(
&recipient,
&U256 {
low: 0x1_u128,
high: 0,
},
)
.send()
.await
.unwrap();

TransactionWaiter::new(tx.transaction_hash, runner.client())
.wait()
.await
.unwrap();
}
8 changes: 7 additions & 1 deletion packages/contracts/controller/src/session/session.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ mod session_component {
use controller::account::IAssertOwner;

const SESSION_MAGIC: felt252 = 'session-token';
const WILDCARD_MAGIC: felt252 = 'wildcard-policy';
const AUTHORIZATION_BY_REGISTERED: felt252 = 'authorization-by-registered';

#[storage]
Expand Down Expand Up @@ -184,7 +185,6 @@ mod session_component {
transaction_hash: felt252,
) -> Option<(felt252, felt252)> {
let contract = self.get_contract();
assert(signature.proofs.len() == calls.len(), 'session/length-mismatch');

let now = get_block_timestamp();
assert(signature.session.expires_at > now, 'session/expired');
Expand Down Expand Up @@ -254,6 +254,12 @@ mod session_component {
);
}

if (signature.session.allowed_policies_root == WILDCARD_MAGIC) {
return to_be_cached;
}

assert(signature.proofs.len() == calls.len(), 'session/length-mismatch');

assert(
check_policy(calls, signature.session.allowed_policies_root, signature.proofs),
'session/policy-check-failed'
Expand Down

0 comments on commit 689a7cd

Please sign in to comment.