1use std::collections::BTreeMap;
6
7use fastcrypto::traits::KeyPair as KeypairTraits;
8use iota_sdk_crypto::{
9 Signer as _, ToFromBytes as _, ed25519::Ed25519PrivateKey, secp256k1::Secp256k1PrivateKey,
10 secp256r1::Secp256r1PrivateKey, simple::SimpleKeypair,
11};
12use iota_sdk_types::{
13 Address, ObjectId, SimpleSignature, TransactionKind, UserSignature, crypto::Intent,
14};
15use rand::{SeedableRng, rngs::StdRng};
16
17use crate::{
18 base_types::{dbg_addr, random_object_ref},
19 committee::Committee,
20 crypto::{
21 AccountKeyPair, AuthorityKeyPair, AuthorityPublicKeyBytes, IotaKeyPair, get_key_pair,
22 get_key_pair_from_rng,
23 },
24 multisig::{MultiSig, MultiSigPublicKey, MultisigMember},
25 object::Object,
26 programmable_transaction_builder::ProgrammableTransactionBuilder,
27 transaction::{
28 SenderSignedData, TEST_ONLY_GAS_UNIT_FOR_TRANSFER, Transaction, TransactionData,
29 TransactionDataAPI,
30 },
31};
32
33pub fn make_committee_key<R>(rand: &mut R) -> (Vec<AuthorityKeyPair>, Committee)
34where
35 R: rand::CryptoRng + rand::RngCore,
36{
37 make_committee_key_num(4, rand)
38}
39
40pub fn make_committee_key_num<R>(num: usize, rand: &mut R) -> (Vec<AuthorityKeyPair>, Committee)
41where
42 R: rand::CryptoRng + rand::RngCore,
43{
44 let mut authorities: BTreeMap<AuthorityPublicKeyBytes, u64> = BTreeMap::new();
45 let mut keys = Vec::new();
46
47 for _ in 0..num {
48 let (_, inner_authority_key): (_, AuthorityKeyPair) = get_key_pair_from_rng(rand);
49 authorities.insert(
50 AuthorityPublicKeyBytes::from(inner_authority_key.public()),
52 1,
54 );
55 keys.push(inner_authority_key);
56 }
57
58 let committee = Committee::new_for_testing_with_normalized_voting_power(0, authorities);
59 (keys, committee)
60}
61
62pub fn create_fake_transaction() -> Transaction {
65 let (sender, sender_key): (_, AccountKeyPair) = get_key_pair();
66 let recipient = dbg_addr(2);
67 let object_id = ObjectId::random();
68 let object = Object::immutable_with_id_for_testing(object_id);
69 let pt = {
70 let mut builder = ProgrammableTransactionBuilder::new();
71 builder.transfer_iota(recipient, None);
72 builder.finish()
73 };
74 let data = TransactionData::new_programmable(
75 sender,
76 vec![object.object_ref()],
77 pt,
78 TEST_ONLY_GAS_UNIT_FOR_TRANSFER, 1,
80 );
81 to_sender_signed_transaction(data, &sender_key)
82}
83
84pub fn make_transaction_data(sender: Address) -> TransactionData {
85 let object =
86 Object::immutable_with_id_for_testing(ObjectId::generate(StdRng::from_seed([0; 32])));
87 let pt = {
88 let mut builder = ProgrammableTransactionBuilder::new();
89 builder.transfer_iota(dbg_addr(2), None);
90 builder.finish()
91 };
92 TransactionData::new_programmable(
93 sender,
94 vec![object.object_ref()],
95 pt,
96 TEST_ONLY_GAS_UNIT_FOR_TRANSFER, 1,
98 )
99}
100
101pub fn make_sponsored_transaction_data(sender: Address, sponsor: Address) -> TransactionData {
104 let pt = {
105 let mut builder = ProgrammableTransactionBuilder::new();
106 builder.transfer_iota(dbg_addr(2), None);
107 builder.finish()
108 };
109 TransactionData::new_with_gas_coins_allow_sponsor(
110 TransactionKind::new_programmable(pt),
111 sender,
112 vec![random_object_ref()],
113 TEST_ONLY_GAS_UNIT_FOR_TRANSFER, 1,
115 sponsor,
116 )
117}
118
119pub fn make_transaction(sender: Address, kp: &SimpleKeypair) -> Transaction {
122 let data = make_transaction_data(sender);
123 let digest = data.signing_digest();
124 Transaction::from_data(data, vec![kp.sign(&digest)])
125}
126
127pub fn to_sender_signed_transaction(
129 data: TransactionData,
130 signer: impl Into<IotaKeyPair>,
131) -> Transaction {
132 to_sender_signed_transaction_with_multi_signers(data, vec![signer])
133}
134
135pub fn to_sender_signed_transaction_with_optional_sponsor(
136 data: TransactionData,
137 sender_signature: UserSignature,
138 sponsor_signer_opt: Option<impl Into<IotaKeyPair>>,
139) -> Transaction {
140 let mut signatures = vec![sender_signature];
141 if let Some(sponsor) = sponsor_signer_opt {
142 let sponsor_sig =
143 Transaction::signature_from_signer(data.clone(), Intent::iota_transaction(), sponsor)
144 .into();
145 signatures.push(sponsor_sig);
146 };
147
148 Transaction::from_user_sig_data(data, signatures)
149}
150
151pub fn to_sender_signed_transaction_with_multi_signers(
152 data: TransactionData,
153 signers: Vec<impl Into<IotaKeyPair>>,
154) -> Transaction {
155 Transaction::from_data_and_signer(data, signers)
156}
157
158pub fn keys() -> Vec<IotaKeyPair> {
159 let mut seed = StdRng::from_seed([0; 32]);
160 let kp1: IotaKeyPair = IotaKeyPair::Ed25519(get_key_pair_from_rng(&mut seed).1);
161 let kp2: IotaKeyPair = IotaKeyPair::Secp256k1(get_key_pair_from_rng(&mut seed).1);
162 let kp3: IotaKeyPair = IotaKeyPair::Secp256r1(get_key_pair_from_rng(&mut seed).1);
163
164 vec![kp1, kp2, kp3]
165}
166
167pub fn multisig_keys() -> (Ed25519PrivateKey, Secp256k1PrivateKey, Secp256r1PrivateKey) {
168 let keys = keys();
169 let kp1 = Ed25519PrivateKey::from_bytes(keys[0].to_bytes_no_flag()).unwrap();
170 let kp2 = Secp256k1PrivateKey::from_bytes(keys[1].to_bytes_no_flag()).unwrap();
171 let kp3 = Secp256r1PrivateKey::from_bytes(keys[2].to_bytes_no_flag()).unwrap();
172
173 (kp1, kp2, kp3)
174}
175
176pub fn make_upgraded_multisig_tx() -> Transaction {
177 let (kp1, kp2, kp3) = multisig_keys();
178 let pk1 = kp1.public_key();
179 let pk2 = kp2.public_key();
180 let pk3 = kp3.public_key();
181
182 let multisig_pk = MultiSigPublicKey::new(
183 vec![
184 MultisigMember::new(pk1, 1),
185 MultisigMember::new(pk2, 1),
186 MultisigMember::new(pk3, 1),
187 ],
188 2,
189 )
190 .unwrap();
191 let addr = Address::from(&multisig_pk);
192 let tx = make_transaction(addr, &SimpleKeypair::from(kp1.clone()));
193
194 let msg = tx.transaction().signing_digest();
195 let sig1: SimpleSignature = kp1.sign(&msg);
196 let sig2: SimpleSignature = kp2.sign(&msg);
197
198 let multi_sig1 = MultiSig::new(vec![sig1.into(), sig2.into()], multisig_pk).unwrap();
200 Transaction::new(SenderSignedData::new(
201 tx.transaction().clone(),
202 vec![UserSignature::Multisig(multi_sig1)],
203 ))
204}
205
206pub fn make_sponsored_regular_sig_tx() -> (Transaction, Address, Address) {
212 let (sender, sender_kp): (_, AccountKeyPair) = get_key_pair();
213 let (sponsor, sponsor_kp): (_, AccountKeyPair) = get_key_pair();
214 let tx_data = make_sponsored_transaction_data(sender, sponsor);
215 let sender_sig: UserSignature =
216 Transaction::signature_from_signer(tx_data.clone(), Intent::iota_transaction(), &sender_kp)
217 .into();
218 let tx =
219 to_sender_signed_transaction_with_optional_sponsor(tx_data, sender_sig, Some(&sponsor_kp));
220 (tx, sender, sponsor)
221}
222
223mod move_authenticator {
224 use fastcrypto::hash::HashFunction;
225 use iota_sdk_types::{Address, Digest, SharedObjectReference, UserSignature};
226 pub use iota_sdk_types::{MoveAuthenticator, MoveAuthenticatorV1};
227
228 use crate::{
229 crypto::DefaultHash,
230 object::OBJECT_START_VERSION,
231 transaction::{SenderSignedData, Transaction},
232 utils::{make_sponsored_transaction_data, make_transaction_data},
233 };
234
235 pub fn make_move_authenticator_tx(address: Address) -> Transaction {
237 let data = make_transaction_data(address);
238 let (authenticator, _) = make_move_authenticator_sig(address);
239 Transaction::new(SenderSignedData::new(data, vec![authenticator]))
240 }
241
242 pub fn make_move_authenticator_sig(address: Address) -> (UserSignature, MoveAuthenticator) {
250 let authenticator =
251 MoveAuthenticator::from(MoveAuthenticatorV1::new_with_shared_account_object(
252 vec![],
253 vec![],
254 SharedObjectReference::new(address.into(), OBJECT_START_VERSION, false),
255 ));
256 let sig = UserSignature::MoveAuthenticator(authenticator.clone());
257 (sig, authenticator)
258 }
259
260 pub fn make_sponsored_move_authenticator_tx(
267 sender_addr: Address,
268 sponsor_addr: Address,
269 ) -> (Transaction, MoveAuthenticator, MoveAuthenticator) {
270 let (sender_sig, sender_auth) = make_move_authenticator_sig(sender_addr);
271 let (sponsor_sig, sponsor_auth) = make_move_authenticator_sig(sponsor_addr);
272 let tx_data = make_sponsored_transaction_data(sender_addr, sponsor_addr);
273 let tx = Transaction::new(SenderSignedData::new(
274 tx_data,
275 vec![sender_sig, sponsor_sig],
276 ));
277 (tx, sender_auth, sponsor_auth)
278 }
279
280 pub fn blake2b256_of_sig(sig: &UserSignature) -> Digest {
285 let mut hasher = DefaultHash::default();
286 hasher.update(sig.to_bytes());
287 Digest::new(hasher.finalize().into())
288 }
289}
290
291pub use move_authenticator::*;
292
293mod passkey {
294 use iota_sdk_crypto::{Signer, secp256r1::Secp256r1PrivateKey};
295 use iota_sdk_types::{UserSignature, crypto::PasskeyAuthenticator};
296
297 use super::*;
298
299 pub fn make_passkey_authenticator_sig() -> UserSignature {
306 let r1_kp = Secp256r1PrivateKey::generate(rand::thread_rng());
307 let user_sig: SimpleSignature = r1_kp.sign(&[0u8; 32]);
308 let client_data_json = r#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","origin":"https://test.iota.org"}"#;
309 let passkey =
310 PasskeyAuthenticator::new(vec![], client_data_json.to_string(), user_sig).unwrap();
311 UserSignature::PasskeyAuthenticator(passkey)
312 }
313}
314
315pub use passkey::*;