use assert_matches::assert_matches;
use miden_protocol::account::auth::{self, PublicKeyCommitment};
use miden_protocol::account::component::AccountComponentMetadata;
use miden_protocol::account::{AccountBuilder, AccountComponent, AccountId, AccountType};
use miden_protocol::asset::{FungibleAsset, NonFungibleAsset, TokenSymbol};
use miden_protocol::crypto::rand::{FeltRng, RandomCoin};
use miden_protocol::errors::NoteError;
use miden_protocol::note::{
Note,
NoteAssets,
NoteAttachment,
NoteMetadata,
NoteRecipient,
NoteStorage,
NoteTag,
NoteType,
};
use miden_protocol::testing::account_id::{
ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE,
ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE_2,
};
use miden_protocol::{Felt, Word};
use crate::AuthMethod;
use crate::account::auth::{AuthMultisig, AuthMultisigConfig, AuthSingleSig, NoAuth};
use crate::account::faucets::BasicFungibleFaucet;
use crate::account::interface::{
AccountComponentInterface,
AccountInterface,
AccountInterfaceExt,
NoteAccountCompatibility,
};
use crate::account::wallets::BasicWallet;
use crate::code_builder::CodeBuilder;
use crate::note::{P2idNote, P2ideNote, P2ideNoteStorage, SwapNote};
use crate::testing::account_interface::get_public_keys_from_account;
#[test]
fn test_basic_wallet_default_notes() {
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let wallet_account = AccountBuilder::new(mock_seed)
.with_auth_component(get_mock_falcon_auth_component())
.with_component(BasicWallet)
.with_assets(vec![FungibleAsset::mock(20)])
.build_existing()
.expect("failed to create wallet account");
let wallet_account_interface = AccountInterface::from_account(&wallet_account);
let mock_seed = Word::from([Felt::new(4), Felt::new(5), Felt::new(6), Felt::new(7)]).as_bytes();
let faucet_account = AccountBuilder::new(mock_seed)
.account_type(AccountType::FungibleFaucet)
.with_auth_component(get_mock_falcon_auth_component())
.with_component(
BasicFungibleFaucet::new(
TokenSymbol::new("POL").expect("invalid token symbol"),
10,
Felt::new(100),
)
.expect("failed to create a fungible faucet component"),
)
.build_existing()
.expect("failed to create wallet account");
let faucet_account_interface = AccountInterface::from_account(&faucet_account);
let p2id_note = P2idNote::create(
ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE.try_into().unwrap(),
ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE_2.try_into().unwrap(),
vec![FungibleAsset::mock(10)],
NoteType::Public,
Default::default(),
&mut RandomCoin::new(Word::from([1, 2, 3, 4u32])),
)
.unwrap();
let sender: AccountId = ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE.try_into().unwrap();
let target: AccountId = ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE_2.try_into().unwrap();
let p2ide_note = P2ideNote::create(
sender,
P2ideNoteStorage::new(target, None, None),
vec![FungibleAsset::mock(10)],
NoteType::Public,
Default::default(),
&mut RandomCoin::new(Word::from([1, 2, 3, 4u32])),
)
.unwrap();
let offered_asset = NonFungibleAsset::mock(&[5, 6, 7, 8]);
let requested_asset = NonFungibleAsset::mock(&[1, 2, 3, 4]);
let (swap_note, _) = SwapNote::create(
ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE.try_into().unwrap(),
offered_asset,
requested_asset,
NoteType::Public,
NoteAttachment::default(),
NoteType::Public,
NoteAttachment::default(),
&mut RandomCoin::new(Word::from([1, 2, 3, 4u32])),
)
.unwrap();
assert_eq!(
NoteAccountCompatibility::Maybe,
wallet_account_interface.is_compatible_with(&p2id_note)
);
assert_eq!(
NoteAccountCompatibility::Maybe,
wallet_account_interface.is_compatible_with(&p2ide_note)
);
assert_eq!(
NoteAccountCompatibility::Maybe,
wallet_account_interface.is_compatible_with(&swap_note)
);
assert_eq!(
NoteAccountCompatibility::No,
faucet_account_interface.is_compatible_with(&p2id_note)
);
assert_eq!(
NoteAccountCompatibility::No,
faucet_account_interface.is_compatible_with(&p2ide_note)
);
assert_eq!(
NoteAccountCompatibility::No,
faucet_account_interface.is_compatible_with(&swap_note)
);
}
#[test]
fn test_custom_account_default_note() {
let account_custom_code_source = "
use miden::standards::wallets::basic
pub use basic::receive_asset
";
let account_code = CodeBuilder::default()
.compile_component_code("test::account_custom", account_custom_code_source)
.unwrap();
let metadata = AccountComponentMetadata::new("test::account_custom", AccountType::all());
let account_component = AccountComponent::new(account_code, vec![], metadata).unwrap();
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let target_account = AccountBuilder::new(mock_seed)
.with_auth_component(get_mock_falcon_auth_component())
.with_component(account_component.clone())
.build_existing()
.unwrap();
let target_account_interface = AccountInterface::from_account(&target_account);
let p2id_note = P2idNote::create(
ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE.try_into().unwrap(),
ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE_2.try_into().unwrap(),
vec![FungibleAsset::mock(10)],
NoteType::Public,
Default::default(),
&mut RandomCoin::new(Word::from([1, 2, 3, 4u32])),
)
.unwrap();
let sender: AccountId = ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE.try_into().unwrap();
let target: AccountId = ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE_2.try_into().unwrap();
let p2ide_note = P2ideNote::create(
sender,
P2ideNoteStorage::new(target, None, None),
vec![FungibleAsset::mock(10)],
NoteType::Public,
Default::default(),
&mut RandomCoin::new(Word::from([1, 2, 3, 4u32])),
)
.unwrap();
let offered_asset = NonFungibleAsset::mock(&[5, 6, 7, 8]);
let requested_asset = NonFungibleAsset::mock(&[1, 2, 3, 4]);
let (swap_note, _) = SwapNote::create(
ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE.try_into().unwrap(),
offered_asset,
requested_asset,
NoteType::Public,
NoteAttachment::default(),
NoteType::Public,
NoteAttachment::default(),
&mut RandomCoin::new(Word::from([1, 2, 3, 4u32])),
)
.unwrap();
assert_eq!(
NoteAccountCompatibility::Maybe,
target_account_interface.is_compatible_with(&p2id_note)
);
assert_eq!(
NoteAccountCompatibility::Maybe,
target_account_interface.is_compatible_with(&p2ide_note)
);
assert_eq!(
NoteAccountCompatibility::No,
target_account_interface.is_compatible_with(&swap_note)
);
}
#[test]
fn test_required_asset_same_as_offered() {
let offered_asset = NonFungibleAsset::mock(&[1, 2, 3, 4]);
let requested_asset = NonFungibleAsset::mock(&[1, 2, 3, 4]);
let result = SwapNote::create(
ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE.try_into().unwrap(),
offered_asset,
requested_asset,
NoteType::Public,
NoteAttachment::default(),
NoteType::Public,
NoteAttachment::default(),
&mut RandomCoin::new(Word::from([1, 2, 3, 4u32])),
);
assert_matches!(result, Err(NoteError::Other { error_msg, .. }) if error_msg == "requested asset same as offered asset".into());
}
#[test]
fn test_basic_wallet_custom_notes() {
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let wallet_account = AccountBuilder::new(mock_seed)
.with_auth_component(get_mock_falcon_auth_component())
.with_component(BasicWallet)
.with_assets(vec![FungibleAsset::mock(20)])
.build_existing()
.expect("failed to create wallet account");
let wallet_account_interface = AccountInterface::from_account(&wallet_account);
let sender_account_id = ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE_2.try_into().unwrap();
let serial_num = RandomCoin::new(Word::from([1, 2, 3, 4u32])).draw_word();
let tag = NoteTag::with_account_target(wallet_account.id());
let metadata = NoteMetadata::new(sender_account_id, NoteType::Public).with_tag(tag);
let vault = NoteAssets::new(vec![FungibleAsset::mock(100)]).unwrap();
let compatible_source_code = "
use miden::protocol::tx
use miden::standards::wallets::basic->wallet
use miden::standards::faucets::basic_fungible->fungible_faucet
@note_script
pub proc main
push.1
if.true
# supported procs
call.wallet::receive_asset
call.wallet::move_asset_to_note
# unsupported procs
call.fungible_faucet::mint_and_send
call.fungible_faucet::burn
else
# supported procs
call.wallet::receive_asset
call.wallet::move_asset_to_note
end
end
";
let note_script = CodeBuilder::default().compile_note_script(compatible_source_code).unwrap();
let recipient = NoteRecipient::new(serial_num, note_script, NoteStorage::default());
let compatible_custom_note = Note::new(vault.clone(), metadata.clone(), recipient);
assert_eq!(
NoteAccountCompatibility::Maybe,
wallet_account_interface.is_compatible_with(&compatible_custom_note)
);
let incompatible_source_code = "
use miden::standards::wallets::basic->wallet
use miden::standards::faucets::basic_fungible->fungible_faucet
@note_script
pub proc main
push.1
if.true
# unsupported procs
call.fungible_faucet::mint_and_send
call.fungible_faucet::burn
else
# unsupported proc
call.fungible_faucet::mint_and_send
# supported procs
call.wallet::receive_asset
call.wallet::move_asset_to_note
end
end
";
let note_script = CodeBuilder::default().compile_note_script(incompatible_source_code).unwrap();
let recipient = NoteRecipient::new(serial_num, note_script, NoteStorage::default());
let incompatible_custom_note = Note::new(vault, metadata, recipient);
assert_eq!(
NoteAccountCompatibility::No,
wallet_account_interface.is_compatible_with(&incompatible_custom_note)
);
}
#[test]
fn test_basic_fungible_faucet_custom_notes() {
let mock_seed = Word::from([Felt::new(4), Felt::new(5), Felt::new(6), Felt::new(7)]).as_bytes();
let faucet_account = AccountBuilder::new(mock_seed)
.account_type(AccountType::FungibleFaucet)
.with_auth_component(get_mock_falcon_auth_component())
.with_component(
BasicFungibleFaucet::new(
TokenSymbol::new("POL").expect("invalid token symbol"),
10,
Felt::new(100),
)
.expect("failed to create a fungible faucet component"),
)
.build_existing()
.expect("failed to create wallet account");
let faucet_account_interface = AccountInterface::from_account(&faucet_account);
let sender_account_id = ACCOUNT_ID_REGULAR_PUBLIC_ACCOUNT_IMMUTABLE_CODE_2.try_into().unwrap();
let serial_num = RandomCoin::new(Word::from([1, 2, 3, 4u32])).draw_word();
let tag = NoteTag::with_account_target(faucet_account.id());
let metadata = NoteMetadata::new(sender_account_id, NoteType::Public).with_tag(tag);
let vault = NoteAssets::new(vec![FungibleAsset::mock(100)]).unwrap();
let compatible_source_code = "
use miden::standards::wallets::basic->wallet
use miden::standards::faucets::basic_fungible->fungible_faucet
@note_script
pub proc main
push.1
if.true
# supported procs
call.fungible_faucet::mint_and_send
call.fungible_faucet::burn
else
# supported proc
call.fungible_faucet::mint_and_send
# unsupported procs
call.wallet::receive_asset
call.wallet::move_asset_to_note
end
end
";
let note_script = CodeBuilder::default().compile_note_script(compatible_source_code).unwrap();
let recipient = NoteRecipient::new(serial_num, note_script, NoteStorage::default());
let compatible_custom_note = Note::new(vault.clone(), metadata.clone(), recipient);
assert_eq!(
NoteAccountCompatibility::Maybe,
faucet_account_interface.is_compatible_with(&compatible_custom_note)
);
let incompatible_source_code = "
use miden::standards::wallets::basic->wallet
use miden::standards::faucets::basic_fungible->fungible_faucet
@note_script
pub proc main
push.1
if.true
# supported procs
call.fungible_faucet::mint_and_send
call.fungible_faucet::burn
# unsupported proc
call.wallet::receive_asset
else
# supported proc
call.fungible_faucet::burn
# unsupported procs
call.wallet::move_asset_to_note
end
end
";
let note_script = CodeBuilder::default().compile_note_script(incompatible_source_code).unwrap();
let recipient = NoteRecipient::new(serial_num, note_script, NoteStorage::default());
let incompatible_custom_note = Note::new(vault, metadata, recipient);
assert_eq!(
NoteAccountCompatibility::No,
faucet_account_interface.is_compatible_with(&incompatible_custom_note)
);
}
#[test]
fn test_custom_account_custom_notes() {
let account_custom_code_source = "
pub proc procedure_1
push.1.2.3.4 dropw
end
pub proc procedure_2
push.5.6.7.8 dropw
end
";
let account_code = CodeBuilder::default()
.compile_component_code("test::account::component_1", account_custom_code_source)
.unwrap();
let metadata = AccountComponentMetadata::new("test::account::component_1", AccountType::all());
let account_component = AccountComponent::new(account_code, vec![], metadata).unwrap();
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let target_account = AccountBuilder::new(mock_seed)
.with_auth_component(get_mock_falcon_auth_component())
.with_component(account_component.clone())
.build_existing()
.unwrap();
let target_account_interface = AccountInterface::from_account(&target_account);
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let sender_account = AccountBuilder::new(mock_seed)
.with_auth_component(get_mock_falcon_auth_component())
.with_component(BasicWallet)
.with_assets(vec![FungibleAsset::mock(20)])
.build_existing()
.expect("failed to create wallet account");
let serial_num = RandomCoin::new(Word::from([1, 2, 3, 4u32])).draw_word();
let tag = NoteTag::with_account_target(target_account.id());
let metadata = NoteMetadata::new(sender_account.id(), NoteType::Public).with_tag(tag);
let vault = NoteAssets::new(vec![FungibleAsset::mock(100)]).unwrap();
let compatible_source_code = "
use miden::standards::wallets::basic->wallet
use test::account::component_1->test_account
@note_script
pub proc main
push.1
if.true
# supported proc
call.test_account::procedure_1
# unsupported proc
call.wallet::receive_asset
else
# supported procs
call.test_account::procedure_1
call.test_account::procedure_2
end
end
";
let note_script = CodeBuilder::default()
.with_dynamically_linked_library(account_component.component_code())
.unwrap()
.compile_note_script(compatible_source_code)
.unwrap();
let recipient = NoteRecipient::new(serial_num, note_script, NoteStorage::default());
let compatible_custom_note = Note::new(vault.clone(), metadata.clone(), recipient);
assert_eq!(
NoteAccountCompatibility::Maybe,
target_account_interface.is_compatible_with(&compatible_custom_note)
);
let incompatible_source_code = "
use miden::standards::wallets::basic->wallet
use test::account::component_1->test_account
@note_script
pub proc main
push.1
if.true
call.wallet::receive_asset
call.test_account::procedure_1
else
call.test_account::procedure_2
call.wallet::move_asset_to_note
end
end
";
let note_script = CodeBuilder::default()
.with_dynamically_linked_library(account_component.component_code())
.unwrap()
.compile_note_script(incompatible_source_code)
.unwrap();
let recipient = NoteRecipient::new(serial_num, note_script, NoteStorage::default());
let incompatible_custom_note = Note::new(vault, metadata, recipient);
assert_eq!(
NoteAccountCompatibility::No,
target_account_interface.is_compatible_with(&incompatible_custom_note)
);
}
#[test]
fn test_custom_account_multiple_components_custom_notes() {
let account_custom_code_source = "
pub proc procedure_1
push.1.2.3.4 dropw
end
pub proc procedure_2
push.5.6.7.8 dropw
end
";
let custom_code = CodeBuilder::default()
.compile_component_code("test::account::component_1", account_custom_code_source)
.unwrap();
let metadata = AccountComponentMetadata::new("test::account::component_1", AccountType::all());
let custom_component = AccountComponent::new(custom_code, vec![], metadata).unwrap();
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let target_account = AccountBuilder::new(mock_seed)
.with_auth_component(get_mock_falcon_auth_component())
.with_component(custom_component.clone())
.with_component(BasicWallet)
.build_existing()
.unwrap();
let target_account_interface = AccountInterface::from_account(&target_account);
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let sender_account = AccountBuilder::new(mock_seed)
.with_auth_component(get_mock_falcon_auth_component())
.with_component(BasicWallet)
.with_assets(vec![FungibleAsset::mock(20)])
.build_existing()
.expect("failed to create wallet account");
let serial_num = RandomCoin::new(Word::from([1, 2, 3, 4u32])).draw_word();
let tag = NoteTag::with_account_target(target_account.id());
let metadata = NoteMetadata::new(sender_account.id(), NoteType::Public).with_tag(tag);
let vault = NoteAssets::new(vec![FungibleAsset::mock(100)]).unwrap();
let compatible_source_code = "
use miden::standards::wallets::basic->wallet
use test::account::component_1->test_account
use miden::standards::faucets::basic_fungible->fungible_faucet
@note_script
pub proc main
push.1
if.true
# supported procs
call.wallet::receive_asset
call.wallet::move_asset_to_note
call.test_account::procedure_1
call.test_account::procedure_2
else
# supported procs
call.wallet::receive_asset
call.wallet::move_asset_to_note
call.test_account::procedure_1
call.test_account::procedure_2
# unsupported proc
call.fungible_faucet::mint_and_send
end
end
";
let note_script = CodeBuilder::default()
.with_dynamically_linked_library(custom_component.component_code())
.unwrap()
.compile_note_script(compatible_source_code)
.unwrap();
let recipient = NoteRecipient::new(serial_num, note_script, NoteStorage::default());
let compatible_custom_note = Note::new(vault.clone(), metadata.clone(), recipient);
assert_eq!(
NoteAccountCompatibility::Maybe,
target_account_interface.is_compatible_with(&compatible_custom_note)
);
let incompatible_source_code = "
use miden::standards::wallets::basic->wallet
use test::account::component_1->test_account
use miden::standards::faucets::basic_fungible->fungible_faucet
@note_script
pub proc main
push.1
if.true
# supported procs
call.wallet::receive_asset
call.wallet::move_asset_to_note
call.test_account::procedure_1
call.test_account::procedure_2
# unsupported proc
call.fungible_faucet::mint_and_send
else
# supported procs
call.test_account::procedure_1
call.test_account::procedure_2
# unsupported proc
call.fungible_faucet::burn
end
end
";
let note_script = CodeBuilder::default()
.with_dynamically_linked_library(custom_component.component_code())
.unwrap()
.compile_note_script(incompatible_source_code)
.unwrap();
let recipient = NoteRecipient::new(serial_num, note_script, NoteStorage::default());
let incompatible_custom_note = Note::new(vault.clone(), metadata, recipient);
assert_eq!(
NoteAccountCompatibility::No,
target_account_interface.is_compatible_with(&incompatible_custom_note)
);
}
fn get_mock_falcon_auth_component() -> AuthSingleSig {
let mock_word = Word::from([0, 1, 2, 3u32]);
let mock_public_key = PublicKeyCommitment::from(mock_word);
AuthSingleSig::new(mock_public_key, auth::AuthScheme::Falcon512Poseidon2)
}
fn get_mock_ecdsa_auth_component() -> AuthSingleSig {
let mock_word = Word::from([0, 1, 2, 3u32]);
let mock_public_key = PublicKeyCommitment::from(mock_word);
AuthSingleSig::new(mock_public_key, auth::AuthScheme::EcdsaK256Keccak)
}
#[test]
fn test_get_auth_scheme_ecdsa_k256_keccak() {
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let wallet_account = AccountBuilder::new(mock_seed)
.with_auth_component(get_mock_ecdsa_auth_component())
.with_component(BasicWallet)
.build_existing()
.expect("failed to create wallet account");
let wallet_account_interface = AccountInterface::from_account(&wallet_account);
let ecdsa_k256_keccak_component = wallet_account_interface
.components()
.iter()
.find(|component| matches!(component, AccountComponentInterface::AuthSingleSig))
.expect("should have EcdsaK256Keccak component");
let auth_methods = ecdsa_k256_keccak_component.get_auth_methods(wallet_account.storage());
assert_eq!(auth_methods.len(), 1);
let auth_method = &auth_methods[0];
match auth_method {
AuthMethod::SingleSig { approver: (pub_key, auth_scheme) } => {
assert_eq!(*pub_key, PublicKeyCommitment::from(Word::from([0, 1, 2, 3u32])));
assert_eq!(*auth_scheme, auth::AuthScheme::EcdsaK256Keccak);
},
_ => panic!("Expected EcdsaK256Keccak auth scheme"),
}
}
#[test]
fn test_get_auth_scheme_falcon512_poseidon2() {
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let wallet_account = AccountBuilder::new(mock_seed)
.with_auth_component(get_mock_falcon_auth_component())
.with_component(BasicWallet)
.build_existing()
.expect("failed to create wallet account");
let wallet_account_interface = AccountInterface::from_account(&wallet_account);
let rpo_falcon_component = wallet_account_interface
.components()
.iter()
.find(|component| matches!(component, AccountComponentInterface::AuthSingleSig))
.expect("should have single sig component");
let auth_methods = rpo_falcon_component.get_auth_methods(wallet_account.storage());
assert_eq!(auth_methods.len(), 1);
let auth_method = &auth_methods[0];
match auth_method {
AuthMethod::SingleSig { approver: (pub_key, auth_scheme) } => {
assert_eq!(*pub_key, PublicKeyCommitment::from(Word::from([0, 1, 2, 3u32])));
assert_eq!(*auth_scheme, auth::AuthScheme::Falcon512Poseidon2);
},
_ => panic!("Expected Falcon512Poseidon2 auth scheme"),
}
}
#[test]
fn test_get_auth_scheme_no_auth() {
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let no_auth_account = AccountBuilder::new(mock_seed)
.with_auth_component(NoAuth)
.with_component(BasicWallet)
.build_existing()
.expect("failed to create no-auth account");
let no_auth_account_interface = AccountInterface::from_account(&no_auth_account);
let no_auth_component = no_auth_account_interface
.components()
.iter()
.find(|component| matches!(component, AccountComponentInterface::AuthNoAuth))
.expect("should have NoAuth component");
let auth_methods = no_auth_component.get_auth_methods(no_auth_account.storage());
assert_eq!(auth_methods.len(), 1);
let auth_method = &auth_methods[0];
match auth_method {
AuthMethod::NoAuth => {},
_ => panic!("Expected NoAuth auth method"),
}
}
#[test]
fn test_get_auth_scheme_non_auth_component() {
let basic_wallet_component = AccountComponentInterface::BasicWallet;
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let wallet_account = AccountBuilder::new(mock_seed)
.with_auth_component(get_mock_falcon_auth_component())
.with_component(BasicWallet)
.build_existing()
.expect("failed to create wallet account");
let auth_methods = basic_wallet_component.get_auth_methods(wallet_account.storage());
assert!(auth_methods.is_empty());
}
#[test]
fn test_account_interface_from_account_uses_get_auth_scheme() {
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let wallet_account = AccountBuilder::new(mock_seed)
.with_auth_component(get_mock_falcon_auth_component())
.with_component(BasicWallet)
.build_existing()
.expect("failed to create wallet account");
let wallet_account_interface = AccountInterface::from_account(&wallet_account);
assert_eq!(wallet_account_interface.auth().len(), 1);
match &wallet_account_interface.auth()[0] {
AuthMethod::SingleSig { approver: (pub_key, auth_scheme) } => {
let expected_pub_key = PublicKeyCommitment::from(Word::from([0, 1, 2, 3u32]));
assert_eq!(*pub_key, expected_pub_key);
assert_eq!(*auth_scheme, auth::AuthScheme::Falcon512Poseidon2);
},
_ => panic!("Expected SingleSig auth method"),
}
let no_auth_account = AccountBuilder::new(mock_seed)
.with_auth_component(NoAuth)
.with_component(BasicWallet)
.build_existing()
.expect("failed to create no-auth account");
let no_auth_account_interface = AccountInterface::from_account(&no_auth_account);
assert_eq!(no_auth_account_interface.auth().len(), 1);
match &no_auth_account_interface.auth()[0] {
AuthMethod::NoAuth => {},
_ => panic!("Expected NoAuth auth method"),
}
}
#[test]
fn test_account_interface_get_auth_scheme() {
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let wallet_account = AccountBuilder::new(mock_seed)
.with_auth_component(get_mock_falcon_auth_component())
.with_component(BasicWallet)
.build_existing()
.expect("failed to create wallet account");
let wallet_account_interface = AccountInterface::from_account(&wallet_account);
assert_eq!(wallet_account_interface.auth().len(), 1);
match &wallet_account_interface.auth()[0] {
AuthMethod::SingleSig { approver: (pub_key, auth_scheme) } => {
assert_eq!(*pub_key, PublicKeyCommitment::from(Word::from([0, 1, 2, 3u32])));
assert_eq!(*auth_scheme, auth::AuthScheme::Falcon512Poseidon2);
},
_ => panic!("Expected SingleSig auth method"),
}
let no_auth_account = AccountBuilder::new(mock_seed)
.with_auth_component(NoAuth)
.with_component(BasicWallet)
.build_existing()
.expect("failed to create no-auth account");
let no_auth_account_interface = AccountInterface::from_account(&no_auth_account);
assert_eq!(no_auth_account_interface.auth().len(), 1);
match &no_auth_account_interface.auth()[0] {
AuthMethod::NoAuth => {},
_ => panic!("Expected NoAuth auth method"),
}
}
#[test]
fn test_public_key_extraction_regular_account() {
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let wallet_account = AccountBuilder::new(mock_seed)
.with_auth_component(get_mock_falcon_auth_component())
.with_component(BasicWallet)
.build_existing()
.expect("failed to create wallet account");
let pub_keys = get_public_keys_from_account(&wallet_account);
assert_eq!(pub_keys.len(), 1);
assert_eq!(pub_keys[0], Word::from([0, 1, 2, 3u32]));
}
#[test]
fn test_public_key_extraction_multisig_account() {
let pub_key_1 = PublicKeyCommitment::from(Word::from([1u32, 0, 0, 0]));
let pub_key_2 = PublicKeyCommitment::from(Word::from([2u32, 0, 0, 0]));
let pub_key_3 = PublicKeyCommitment::from(Word::from([3u32, 0, 0, 0]));
let approvers = vec![
(pub_key_1, auth::AuthScheme::Falcon512Poseidon2),
(pub_key_2, auth::AuthScheme::Falcon512Poseidon2),
(pub_key_3, auth::AuthScheme::EcdsaK256Keccak),
];
let threshold = 2u32;
let multisig_component =
AuthMultisig::new(AuthMultisigConfig::new(approvers.clone(), threshold).unwrap())
.expect("multisig component creation failed");
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let multisig_account = AccountBuilder::new(mock_seed)
.with_auth_component(multisig_component)
.with_component(BasicWallet)
.build_existing()
.expect("failed to create multisig account");
let pub_keys = get_public_keys_from_account(&multisig_account);
assert_eq!(pub_keys.len(), 3);
assert_eq!(pub_keys[0], Word::from([1u32, 0, 0, 0]));
assert_eq!(pub_keys[1], Word::from([2u32, 0, 0, 0]));
assert_eq!(pub_keys[2], Word::from([3u32, 0, 0, 0]));
}
#[test]
fn test_public_key_extraction_no_auth_account() {
let mock_seed = Word::from([0, 1, 2, 3u32]).as_bytes();
let no_auth_account = AccountBuilder::new(mock_seed)
.with_auth_component(NoAuth)
.with_component(BasicWallet)
.build_existing()
.expect("failed to create no-auth account");
let pub_keys = get_public_keys_from_account(&no_auth_account);
assert_eq!(pub_keys.len(), 0);
}