1use std::collections::BTreeMap;
6
7use fastcrypto::traits::KeyPair as KeypairTraits;
8use iota_sdk_crypto::{
9 Signer, ed25519::Ed25519PrivateKey, secp256k1::Secp256k1PrivateKey,
10 secp256r1::Secp256r1PrivateKey, simple::SimpleKeypair,
11};
12use iota_sdk_types::{
13 Address, ObjectId, SenderSignedTransaction, SimpleSignature, Transaction, TransactionKind,
14 UserSignature,
15 crypto::{Intent, MultisigAggregatedSignature, MultisigCommittee, MultisigMember},
16};
17use rand::{SeedableRng, rngs::StdRng};
18
19use crate::{
20 base_types::{dbg_addr, random_object_ref},
21 committee::Committee,
22 crypto::{
23 AccountKeyPair, AuthorityKeyPair, AuthorityPublicKeyBytes, get_key_pair,
24 get_key_pair_from_rng,
25 },
26 object::Object,
27 programmable_transaction_builder::ProgrammableTransactionBuilder,
28 transaction::{TEST_ONLY_GAS_UNIT_FOR_TRANSFER, TransactionAPI, TransactionEnvelope},
29};
30
31pub fn make_committee_key<R>(rand: &mut R) -> (Vec<AuthorityKeyPair>, Committee)
32where
33 R: rand::CryptoRng + rand::RngCore,
34{
35 make_committee_key_num(4, rand)
36}
37
38pub fn make_committee_key_num<R>(num: usize, rand: &mut R) -> (Vec<AuthorityKeyPair>, Committee)
39where
40 R: rand::CryptoRng + rand::RngCore,
41{
42 let mut authorities: BTreeMap<AuthorityPublicKeyBytes, u64> = BTreeMap::new();
43 let mut keys = Vec::new();
44
45 for _ in 0..num {
46 let (_, inner_authority_key): (_, AuthorityKeyPair) = get_key_pair_from_rng(rand);
47 authorities.insert(
48 AuthorityPublicKeyBytes::from(inner_authority_key.public()),
50 1,
52 );
53 keys.push(inner_authority_key);
54 }
55
56 let committee = Committee::new_for_testing_with_normalized_voting_power(0, authorities);
57 (keys, committee)
58}
59
60pub fn create_fake_transaction() -> TransactionEnvelope {
63 let (sender, sender_key): (_, AccountKeyPair) = get_key_pair();
64 let recipient = dbg_addr(2);
65 let object_id = ObjectId::random();
66 let object = Object::immutable_with_id_for_testing(object_id);
67 let pt = {
68 let mut builder = ProgrammableTransactionBuilder::new();
69 builder.transfer_iota(recipient, None);
70 builder.finish()
71 };
72 let tx = Transaction::new_programmable(
73 sender,
74 vec![object.object_ref()],
75 pt,
76 TEST_ONLY_GAS_UNIT_FOR_TRANSFER, 1,
78 );
79 to_sender_signed_transaction(tx, &sender_key)
80}
81
82pub fn make_transaction_data(sender: Address) -> Transaction {
83 let object =
84 Object::immutable_with_id_for_testing(ObjectId::random_with(StdRng::from_seed([0; 32])));
85 let pt = {
86 let mut builder = ProgrammableTransactionBuilder::new();
87 builder.transfer_iota(dbg_addr(2), None);
88 builder.finish()
89 };
90 Transaction::new_programmable(
91 sender,
92 vec![object.object_ref()],
93 pt,
94 TEST_ONLY_GAS_UNIT_FOR_TRANSFER, 1,
96 )
97}
98
99pub fn make_sponsored_transaction_data(sender: Address, sponsor: Address) -> Transaction {
102 let pt = {
103 let mut builder = ProgrammableTransactionBuilder::new();
104 builder.transfer_iota(dbg_addr(2), None);
105 builder.finish()
106 };
107 Transaction::new_with_gas_coins_allow_sponsor(
108 TransactionKind::new_programmable(pt),
109 sender,
110 vec![random_object_ref()],
111 TEST_ONLY_GAS_UNIT_FOR_TRANSFER, 1,
113 sponsor,
114 )
115}
116
117pub fn make_transaction(sender: Address, kp: &SimpleKeypair) -> TransactionEnvelope {
120 let data = make_transaction_data(sender);
121 TransactionEnvelope::from_data_and_signer(data, vec![kp])
122}
123
124pub fn to_sender_signed_transaction(
126 tx: Transaction,
127 signer: &impl Signer<SimpleSignature>,
128) -> TransactionEnvelope {
129 to_sender_signed_transaction_with_multi_signers(tx, vec![signer])
130}
131
132pub fn to_sender_signed_transaction_with_optional_sponsor(
133 tx: Transaction,
134 sender_signature: UserSignature,
135 sponsor_signer_opt: Option<&impl Signer<SimpleSignature>>,
136) -> TransactionEnvelope {
137 let mut signatures = vec![sender_signature];
138 if let Some(sponsor) = sponsor_signer_opt {
139 let sponsor_sig = TransactionEnvelope::signature_from_signer(
140 tx.clone(),
141 Intent::iota_transaction(),
142 sponsor,
143 )
144 .into();
145 signatures.push(sponsor_sig);
146 };
147
148 TransactionEnvelope::from_user_sig_data(tx, signatures)
149}
150
151pub fn to_sender_signed_transaction_with_multi_signers(
152 tx: Transaction,
153 signers: Vec<&impl Signer<SimpleSignature>>,
154) -> TransactionEnvelope {
155 TransactionEnvelope::from_data_and_signer(tx, signers)
156}
157
158pub fn make_upgraded_multisig_tx() -> TransactionEnvelope {
159 let kp1 = Ed25519PrivateKey::random();
160 let kp2 = Secp256k1PrivateKey::random();
161 let kp3 = Secp256r1PrivateKey::random();
162 let pk1 = kp1.public_key();
163 let pk2 = kp2.public_key();
164 let pk3 = kp3.public_key();
165
166 let multisig_pk = MultisigCommittee::new(
167 vec![
168 MultisigMember::new(pk1, 1),
169 MultisigMember::new(pk2, 1),
170 MultisigMember::new(pk3, 1),
171 ],
172 2,
173 )
174 .unwrap();
175 let addr = Address::from(&multisig_pk);
176 let tx = make_transaction(addr, &SimpleKeypair::from(kp1.clone()));
177
178 let msg = tx.transaction().signing_digest();
179 let sig1: SimpleSignature = kp1.sign(&msg);
180 let sig2: SimpleSignature = kp2.sign(&msg);
181
182 let multi_sig1 =
184 MultisigAggregatedSignature::new(vec![sig1.into(), sig2.into()], multisig_pk).unwrap();
185 TransactionEnvelope::new(SenderSignedTransaction::new(
186 tx.transaction().clone(),
187 vec![UserSignature::Multisig(multi_sig1)],
188 ))
189}
190
191pub fn make_sponsored_regular_sig_tx() -> (TransactionEnvelope, Address, Address) {
197 let (sender, sender_kp): (_, AccountKeyPair) = get_key_pair();
198 let (sponsor, sponsor_kp): (_, AccountKeyPair) = get_key_pair();
199 let tx_data = make_sponsored_transaction_data(sender, sponsor);
200 let sender_sig: UserSignature = TransactionEnvelope::signature_from_signer(
201 tx_data.clone(),
202 Intent::iota_transaction(),
203 &sender_kp,
204 )
205 .into();
206 let tx =
207 to_sender_signed_transaction_with_optional_sponsor(tx_data, sender_sig, Some(&sponsor_kp));
208 (tx, sender, sponsor)
209}
210
211mod move_authenticator {
212 use fastcrypto::hash::HashFunction;
213 use iota_sdk_types::{
214 Address, Digest, MoveAuthenticator, MoveAuthenticatorV1, SenderSignedTransaction,
215 SharedObjectReference, UserSignature,
216 };
217
218 use crate::{
219 crypto::DefaultHash,
220 object::OBJECT_START_VERSION,
221 transaction::TransactionEnvelope,
222 utils::{make_sponsored_transaction_data, make_transaction_data},
223 };
224
225 pub fn make_move_authenticator_tx(address: Address) -> TransactionEnvelope {
227 let data = make_transaction_data(address);
228 let (authenticator, _) = make_move_authenticator_sig(address);
229 TransactionEnvelope::new(SenderSignedTransaction::new(data, vec![authenticator]))
230 }
231
232 pub fn make_move_authenticator_sig(address: Address) -> (UserSignature, MoveAuthenticator) {
240 let authenticator =
241 MoveAuthenticator::from(MoveAuthenticatorV1::new_with_shared_account_object(
242 vec![],
243 vec![],
244 SharedObjectReference::new(address.into(), OBJECT_START_VERSION, false),
245 ));
246 let sig = UserSignature::MoveAuthenticator(authenticator.clone());
247 (sig, authenticator)
248 }
249
250 pub fn make_sponsored_move_authenticator_tx(
257 sender_addr: Address,
258 sponsor_addr: Address,
259 ) -> (TransactionEnvelope, MoveAuthenticator, MoveAuthenticator) {
260 let (sender_sig, sender_auth) = make_move_authenticator_sig(sender_addr);
261 let (sponsor_sig, sponsor_auth) = make_move_authenticator_sig(sponsor_addr);
262 let tx_data = make_sponsored_transaction_data(sender_addr, sponsor_addr);
263 let tx = TransactionEnvelope::new(SenderSignedTransaction::new(
264 tx_data,
265 vec![sender_sig, sponsor_sig],
266 ));
267 (tx, sender_auth, sponsor_auth)
268 }
269
270 pub fn blake2b256_of_sig(sig: &UserSignature) -> Digest {
275 let mut hasher = DefaultHash::default();
276 hasher.update(sig.to_bytes());
277 Digest::new(hasher.finalize().into())
278 }
279}
280
281pub use move_authenticator::*;
282
283mod passkey {
284 use iota_sdk_crypto::secp256r1::Secp256r1PrivateKey;
285 use iota_sdk_types::crypto::PasskeyAuthenticator;
286
287 use super::*;
288
289 pub fn make_passkey_authenticator_sig() -> UserSignature {
296 let r1_kp = Secp256r1PrivateKey::random();
297 let user_sig: SimpleSignature = r1_kp.sign(&[0u8; 32]);
298 let client_data_json = r#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","origin":"https://test.iota.org"}"#;
299 let passkey =
300 PasskeyAuthenticator::new(vec![], client_data_json.to_string(), user_sig).unwrap();
301 UserSignature::PasskeyAuthenticator(passkey)
302 }
303}
304
305pub use passkey::*;