Skip to content

Commit

Permalink
feat: dynamic signer interactivity (#648)
Browse files Browse the repository at this point in the history
  • Loading branch information
xJonathanLEI authored Aug 9, 2024
1 parent f31e426 commit 2ddc694
Show file tree
Hide file tree
Showing 17 changed files with 102 additions and 52 deletions.
4 changes: 2 additions & 2 deletions examples/mint_tokens.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use starknet::{
accounts::{Account, Call, ExecutionEncoding, SingleOwnerAccount},
accounts::{Account, ExecutionEncoding, SingleOwnerAccount},
core::{
chain_id,
types::{BlockId, BlockTag, Felt},
types::{BlockId, BlockTag, Call, Felt},
utils::get_selector_from_name,
},
providers::{
Expand Down
4 changes: 2 additions & 2 deletions examples/transfer_with_ledger.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use starknet::{
accounts::{Account, Call, ExecutionEncoding, SingleOwnerAccount},
accounts::{Account, ExecutionEncoding, SingleOwnerAccount},
core::{
chain_id,
types::{BlockId, BlockTag, Felt},
types::{BlockId, BlockTag, Call, Felt},
utils::get_selector_from_name,
},
macros::felt,
Expand Down
28 changes: 22 additions & 6 deletions starknet-accounts/src/account/declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use starknet_core::{
};
use starknet_crypto::PoseidonHasher;
use starknet_providers::Provider;
use starknet_signers::SignerInteractivityContext;
use std::sync::Arc;

/// Cairo string for "declare"
Expand Down Expand Up @@ -209,7 +210,9 @@ where
&self,
nonce: Felt,
) -> Result<FeeEstimate, AccountError<A::SignError>> {
let skip_signature = self.account.is_signer_interactive();
let skip_signature = self
.account
.is_signer_interactive(SignerInteractivityContext::Other);

let prepared = PreparedDeclarationV2 {
account: self.account,
Expand Down Expand Up @@ -245,7 +248,10 @@ where
skip_validate: bool,
skip_fee_charge: bool,
) -> Result<SimulatedTransaction, AccountError<A::SignError>> {
let skip_signature = if self.account.is_signer_interactive() {
let skip_signature = if self
.account
.is_signer_interactive(SignerInteractivityContext::Other)
{
// If signer is interactive, we would try to minimize signing requests. However, if the
// caller has decided to not skip validation, it's best we still request a real
// signature, as otherwise the simulation would most likely fail.
Expand Down Expand Up @@ -519,7 +525,9 @@ where
&self,
nonce: Felt,
) -> Result<FeeEstimate, AccountError<A::SignError>> {
let skip_signature = self.account.is_signer_interactive();
let skip_signature = self
.account
.is_signer_interactive(SignerInteractivityContext::Other);

let prepared = PreparedDeclarationV3 {
account: self.account,
Expand Down Expand Up @@ -556,7 +564,10 @@ where
skip_validate: bool,
skip_fee_charge: bool,
) -> Result<SimulatedTransaction, AccountError<A::SignError>> {
let skip_signature = if self.account.is_signer_interactive() {
let skip_signature = if self
.account
.is_signer_interactive(SignerInteractivityContext::Other)
{
// If signer is interactive, we would try to minimize signing requests. However, if the
// caller has decided to not skip validation, it's best we still request a real
// signature, as otherwise the simulation would most likely fail.
Expand Down Expand Up @@ -753,7 +764,9 @@ where
&self,
nonce: Felt,
) -> Result<FeeEstimate, AccountError<A::SignError>> {
let skip_signature = self.account.is_signer_interactive();
let skip_signature = self
.account
.is_signer_interactive(SignerInteractivityContext::Other);

let prepared = PreparedLegacyDeclaration {
account: self.account,
Expand Down Expand Up @@ -788,7 +801,10 @@ where
skip_validate: bool,
skip_fee_charge: bool,
) -> Result<SimulatedTransaction, AccountError<A::SignError>> {
let skip_signature = if self.account.is_signer_interactive() {
let skip_signature = if self
.account
.is_signer_interactive(SignerInteractivityContext::Other)
{
// If signer is interactive, we would try to minimize signing requests. However, if the
// caller has decided to not skip validation, it's best we still request a real
// signature, as otherwise the simulation would most likely fail.
Expand Down
27 changes: 19 additions & 8 deletions starknet-accounts/src/account/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ use super::{
super::NotPreparedError, Account, AccountError, ConnectedAccount, ExecutionV1, ExecutionV3,
PreparedExecutionV1, PreparedExecutionV3, RawExecutionV1, RawExecutionV3,
};
use crate::{Call, ExecutionEncoder};
use crate::ExecutionEncoder;

use starknet_core::{
crypto::compute_hash_on_elements,
types::{
BroadcastedInvokeTransaction, BroadcastedInvokeTransactionV1,
BroadcastedInvokeTransactionV3, BroadcastedTransaction, DataAvailabilityMode, FeeEstimate,
Felt, InvokeTransactionResult, ResourceBounds, ResourceBoundsMapping, SimulatedTransaction,
SimulationFlag, SimulationFlagForEstimateFee,
BroadcastedInvokeTransactionV3, BroadcastedTransaction, Call, DataAvailabilityMode,
FeeEstimate, Felt, InvokeTransactionResult, ResourceBounds, ResourceBoundsMapping,
SimulatedTransaction, SimulationFlag, SimulationFlagForEstimateFee,
},
};
use starknet_crypto::PoseidonHasher;
use starknet_providers::Provider;
use starknet_signers::SignerInteractivityContext;

/// Cairo string for "invoke"
const PREFIX_INVOKE: Felt = Felt::from_raw([
Expand Down Expand Up @@ -271,7 +272,9 @@ where
&self,
nonce: Felt,
) -> Result<FeeEstimate, AccountError<A::SignError>> {
let skip_signature = self.account.is_signer_interactive();
let skip_signature = self
.account
.is_signer_interactive(SignerInteractivityContext::Execution { calls: &self.calls });

let prepared = PreparedExecutionV1 {
account: self.account,
Expand Down Expand Up @@ -309,7 +312,10 @@ where
skip_validate: bool,
skip_fee_charge: bool,
) -> Result<SimulatedTransaction, AccountError<A::SignError>> {
let skip_signature = if self.account.is_signer_interactive() {
let skip_signature = if self
.account
.is_signer_interactive(SignerInteractivityContext::Execution { calls: &self.calls })
{
// If signer is interactive, we would try to minimize signing requests. However, if the
// caller has decided to not skip validation, it's best we still request a real
// signature, as otherwise the simulation would most likely fail.
Expand Down Expand Up @@ -498,7 +504,9 @@ where
&self,
nonce: Felt,
) -> Result<FeeEstimate, AccountError<A::SignError>> {
let skip_signature = self.account.is_signer_interactive();
let skip_signature = self
.account
.is_signer_interactive(SignerInteractivityContext::Execution { calls: &self.calls });

let prepared = PreparedExecutionV3 {
account: self.account,
Expand Down Expand Up @@ -537,7 +545,10 @@ where
skip_validate: bool,
skip_fee_charge: bool,
) -> Result<SimulatedTransaction, AccountError<A::SignError>> {
let skip_signature = if self.account.is_signer_interactive() {
let skip_signature = if self
.account
.is_signer_interactive(SignerInteractivityContext::Execution { calls: &self.calls })
{
// If signer is interactive, we would try to minimize signing requests. However, if the
// caller has decided to not skip validation, it's best we still request a real
// signature, as otherwise the simulation would most likely fail.
Expand Down
19 changes: 9 additions & 10 deletions starknet-accounts/src/account/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use crate::Call;

use async_trait::async_trait;
use auto_impl::auto_impl;
use starknet_core::types::{
contract::{legacy::LegacyContractClass, CompressProgramError, ComputeClassHashError},
BlockId, BlockTag, Felt, FlattenedSierraClass,
BlockId, BlockTag, Call, Felt, FlattenedSierraClass,
};
use starknet_providers::{Provider, ProviderError};
use starknet_signers::SignerInteractivityContext;
use std::{error::Error, sync::Arc};

mod declaration;
Expand Down Expand Up @@ -89,7 +88,7 @@ pub trait Account: ExecutionEncoder + Sized {
///
/// This affects how an account makes decision on whether to request a real signature for
/// estimation/simulation purposes.
fn is_signer_interactive(&self) -> bool;
fn is_signer_interactive(&self, context: SignerInteractivityContext<'_>) -> bool;

/// Generates an instance of [`ExecutionV1`] for sending `INVOKE` v1 transactions. Pays
/// transaction fees in `ETH`.
Expand Down Expand Up @@ -465,8 +464,8 @@ where
.await
}

fn is_signer_interactive(&self) -> bool {
(*self).is_signer_interactive()
fn is_signer_interactive(&self, context: SignerInteractivityContext<'_>) -> bool {
(*self).is_signer_interactive(context)
}
}

Expand Down Expand Up @@ -532,8 +531,8 @@ where
.await
}

fn is_signer_interactive(&self) -> bool {
self.as_ref().is_signer_interactive()
fn is_signer_interactive(&self, context: SignerInteractivityContext<'_>) -> bool {
self.as_ref().is_signer_interactive(context)
}
}

Expand Down Expand Up @@ -599,8 +598,8 @@ where
.await
}

fn is_signer_interactive(&self) -> bool {
self.as_ref().is_signer_interactive()
fn is_signer_interactive(&self, context: SignerInteractivityContext<'_>) -> bool {
self.as_ref().is_signer_interactive(context)
}
}

Expand Down
5 changes: 3 additions & 2 deletions starknet-accounts/src/factory/argent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
use async_trait::async_trait;
use starknet_core::types::{BlockId, BlockTag, Felt};
use starknet_providers::Provider;
use starknet_signers::Signer;
use starknet_signers::{Signer, SignerInteractivityContext};

/// [`AccountFactory`] implementation for deploying `Argent X` account contracts.
#[derive(Debug)]
Expand Down Expand Up @@ -78,7 +78,8 @@ where
}

fn is_signer_interactive(&self) -> bool {
self.signer.is_interactive()
self.signer
.is_interactive(SignerInteractivityContext::Other)
}

fn block_id(&self) -> BlockId {
Expand Down
5 changes: 3 additions & 2 deletions starknet-accounts/src/factory/open_zeppelin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
use async_trait::async_trait;
use starknet_core::types::{BlockId, BlockTag, Felt};
use starknet_providers::Provider;
use starknet_signers::Signer;
use starknet_signers::{Signer, SignerInteractivityContext};

/// [`AccountFactory`] implementation for deploying `OpenZeppelin` account contracts.
#[derive(Debug)]
Expand Down Expand Up @@ -75,7 +75,8 @@ where
}

fn is_signer_interactive(&self) -> bool {
self.signer.is_interactive()
self.signer
.is_interactive(SignerInteractivityContext::Other)
}

fn block_id(&self) -> BlockId {
Expand Down
3 changes: 0 additions & 3 deletions starknet-accounts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ pub use account::{
RawDeclarationV3, RawExecutionV1, RawExecutionV3, RawLegacyDeclaration,
};

mod call;
pub use call::Call;

mod factory;
pub use factory::{
argent::ArgentAccountFactory, open_zeppelin::OpenZeppelinAccountFactory, AccountDeploymentV1,
Expand Down
10 changes: 5 additions & 5 deletions starknet-accounts/src/single_owner.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::{
Account, Call, ConnectedAccount, ExecutionEncoder, RawDeclarationV2, RawDeclarationV3,
Account, ConnectedAccount, ExecutionEncoder, RawDeclarationV2, RawDeclarationV3,
RawExecutionV1, RawExecutionV3, RawLegacyDeclaration,
};

use async_trait::async_trait;
use starknet_core::types::{contract::ComputeClassHashError, BlockId, BlockTag, Felt};
use starknet_core::types::{contract::ComputeClassHashError, BlockId, BlockTag, Call, Felt};
use starknet_providers::Provider;
use starknet_signers::Signer;
use starknet_signers::{Signer, SignerInteractivityContext};

/// A generic [`Account`] implementation for controlling account contracts that only have one signer
/// using ECDSA the STARK curve.
Expand Down Expand Up @@ -177,8 +177,8 @@ where
Ok(vec![signature.r, signature.s])
}

fn is_signer_interactive(&self) -> bool {
self.signer.is_interactive()
fn is_signer_interactive(&self, context: SignerInteractivityContext<'_>) -> bool {
self.signer.is_interactive(context)
}
}

Expand Down
4 changes: 2 additions & 2 deletions starknet-accounts/tests/single_owner_account.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use starknet_accounts::{
Account, AccountError, Call, ConnectedAccount, ExecutionEncoding, SingleOwnerAccount,
Account, AccountError, ConnectedAccount, ExecutionEncoding, SingleOwnerAccount,
};
use starknet_core::{
types::{
contract::{
legacy::{LegacyContractClass, RawLegacyAbiEntry, RawLegacyFunction},
SierraClass,
},
BlockId, BlockTag, Felt, StarknetError,
BlockId, BlockTag, Call, Felt, StarknetError,
},
utils::get_selector_from_name,
};
Expand Down
4 changes: 2 additions & 2 deletions starknet-contract/src/factory.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use starknet_accounts::{Account, AccountError, Call, ConnectedAccount, ExecutionV1, ExecutionV3};
use starknet_accounts::{Account, AccountError, ConnectedAccount, ExecutionV1, ExecutionV3};
use starknet_core::{
types::{FeeEstimate, Felt, InvokeTransactionResult, SimulatedTransaction},
types::{Call, FeeEstimate, Felt, InvokeTransactionResult, SimulatedTransaction},
utils::{get_udc_deployed_address, UdcUniqueSettings, UdcUniqueness},
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use starknet_core::types::Felt;
use alloc::vec::*;

use crate::types::Felt;

/// A contract call as part of a multi-call execution request.
#[derive(Debug, Clone)]
Expand Down
3 changes: 3 additions & 0 deletions starknet-core/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ pub use receipt_block::ReceiptBlock;
mod msg;
pub use msg::MsgToL2;

mod call;
pub use call::Call;

// TODO: move generated request code to `starknet-providers`
/// Module containing JSON-RPC request types.
pub mod requests;
Expand Down
4 changes: 2 additions & 2 deletions starknet-signers/src/ledger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crypto_bigint::{ArrayEncoding, U256};
use semver::Version;
use starknet_core::{crypto::Signature, types::Felt};

use crate::{Signer, VerifyingKey};
use crate::{Signer, SignerInteractivityContext, VerifyingKey};

pub use coins_bip32::path::DerivationPath;

Expand Down Expand Up @@ -128,7 +128,7 @@ impl Signer for LedgerSigner {
self.app.sign_hash(self.derivation_path.clone(), hash).await
}

fn is_interactive(&self) -> bool {
fn is_interactive(&self, _context: SignerInteractivityContext<'_>) -> bool {
true
}
}
Expand Down
2 changes: 1 addition & 1 deletion starknet-signers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub use key_pair::{SigningKey, VerifyingKey};
pub use key_pair::KeystoreError;

mod signer;
pub use signer::Signer;
pub use signer::{Signer, SignerInteractivityContext};

/// Module containing types related to the use of a simple in-memory signer.
pub mod local_wallet;
Expand Down
4 changes: 2 additions & 2 deletions starknet-signers/src/local_wallet.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Infallible, Signer, SigningKey, VerifyingKey};
use crate::{Infallible, Signer, SignerInteractivityContext, SigningKey, VerifyingKey};

use async_trait::async_trait;
use starknet_core::{
Expand Down Expand Up @@ -42,7 +42,7 @@ impl Signer for LocalWallet {
Ok(self.private_key.sign(hash)?)
}

fn is_interactive(&self) -> bool {
fn is_interactive(&self, _context: SignerInteractivityContext<'_>) -> bool {
false
}
}
Expand Down
Loading

0 comments on commit 2ddc694

Please sign in to comment.