1use std::collections::BTreeMap;
6
7use fastcrypto::traits::KeyPair as KeypairTraits;
8use iota_sdk_crypto::{
9 Signer as _, ToFromBytes, ed25519::Ed25519PrivateKey, secp256k1::Secp256k1PrivateKey,
10 secp256r1::Secp256r1PrivateKey, simple::SimpleKeypair,
11};
12use iota_sdk_types::{
13 ObjectId, SimpleSignature,
14 crypto::{Intent, IntentMessage},
15};
16use rand::{SeedableRng, rngs::StdRng};
17
18use crate::{
19 IotaAddress,
20 base_types::{dbg_addr, random_object_ref},
21 committee::Committee,
22 crypto::{
23 AccountKeyPair, AuthorityKeyPair, AuthorityPublicKeyBytes, IotaKeyPair, Signature, Signer,
24 get_key_pair, get_key_pair_from_rng,
25 },
26 multisig::{MultiSig, MultiSigPublicKey, MultisigMember},
27 object::Object,
28 programmable_transaction_builder::ProgrammableTransactionBuilder,
29 signature::GenericSignature,
30 transaction::{
31 SenderSignedData, TEST_ONLY_GAS_UNIT_FOR_TRANSFER, Transaction, TransactionData,
32 TransactionDataAPI, TransactionKind,
33 },
34};
35
36pub fn make_committee_key<R>(rand: &mut R) -> (Vec<AuthorityKeyPair>, Committee)
37where
38 R: rand::CryptoRng + rand::RngCore,
39{
40 make_committee_key_num(4, rand)
41}
42
43pub fn make_committee_key_num<R>(num: usize, rand: &mut R) -> (Vec<AuthorityKeyPair>, Committee)
44where
45 R: rand::CryptoRng + rand::RngCore,
46{
47 let mut authorities: BTreeMap<AuthorityPublicKeyBytes, u64> = BTreeMap::new();
48 let mut keys = Vec::new();
49
50 for _ in 0..num {
51 let (_, inner_authority_key): (_, AuthorityKeyPair) = get_key_pair_from_rng(rand);
52 authorities.insert(
53 AuthorityPublicKeyBytes::from(inner_authority_key.public()),
55 1,
57 );
58 keys.push(inner_authority_key);
59 }
60
61 let committee = Committee::new_for_testing_with_normalized_voting_power(0, authorities);
62 (keys, committee)
63}
64
65pub fn create_fake_transaction() -> Transaction {
68 let (sender, sender_key): (_, AccountKeyPair) = get_key_pair();
69 let recipient = dbg_addr(2);
70 let object_id = ObjectId::random();
71 let object = Object::immutable_with_id_for_testing(object_id);
72 let pt = {
73 let mut builder = ProgrammableTransactionBuilder::new();
74 builder.transfer_iota(recipient, None);
75 builder.finish()
76 };
77 let data = TransactionData::new_programmable(
78 sender,
79 vec![object.compute_object_reference()],
80 pt,
81 TEST_ONLY_GAS_UNIT_FOR_TRANSFER, 1,
83 );
84 to_sender_signed_transaction(data, &sender_key)
85}
86
87pub fn make_transaction_data(sender: IotaAddress) -> TransactionData {
88 let object =
89 Object::immutable_with_id_for_testing(ObjectId::generate(StdRng::from_seed([0; 32])));
90 let pt = {
91 let mut builder = ProgrammableTransactionBuilder::new();
92 builder.transfer_iota(dbg_addr(2), None);
93 builder.finish()
94 };
95 TransactionData::new_programmable(
96 sender,
97 vec![object.compute_object_reference()],
98 pt,
99 TEST_ONLY_GAS_UNIT_FOR_TRANSFER, 1,
101 )
102}
103
104pub fn make_sponsored_transaction_data(
107 sender: IotaAddress,
108 sponsor: IotaAddress,
109) -> TransactionData {
110 let pt = {
111 let mut builder = ProgrammableTransactionBuilder::new();
112 builder.transfer_iota(dbg_addr(2), None);
113 builder.finish()
114 };
115 TransactionData::new_with_gas_coins_allow_sponsor(
116 TransactionKind::new_programmable(pt),
117 sender,
118 vec![random_object_ref()],
119 TEST_ONLY_GAS_UNIT_FOR_TRANSFER, 1,
121 sponsor,
122 )
123}
124
125pub fn make_transaction(sender: IotaAddress, kp: &SimpleKeypair) -> Transaction {
128 let data = make_transaction_data(sender);
129 let kp = IotaKeyPair::from_bytes(&kp.to_bytes()).unwrap();
131 Transaction::from_data_and_signer(data, vec![&kp])
132}
133
134pub fn to_sender_signed_transaction(
136 data: TransactionData,
137 signer: &dyn Signer<Signature>,
138) -> Transaction {
139 to_sender_signed_transaction_with_multi_signers(data, vec![signer])
140}
141
142pub fn to_sender_signed_transaction_with_optional_sponsor(
143 data: TransactionData,
144 sender_signature: GenericSignature,
145 sponsor_signer_opt: Option<&dyn Signer<Signature>>,
146) -> Transaction {
147 let mut signatures = vec![sender_signature];
148 if let Some(sponsor) = sponsor_signer_opt {
149 let sponsor_sig =
150 Transaction::signature_from_signer(data.clone(), Intent::iota_transaction(), sponsor)
151 .into();
152 signatures.push(sponsor_sig);
153 };
154
155 Transaction::from_generic_sig_data(data, signatures)
156}
157
158pub fn to_sender_signed_transaction_with_multi_signers(
159 data: TransactionData,
160 signers: Vec<&dyn Signer<Signature>>,
161) -> Transaction {
162 Transaction::from_data_and_signer(data, signers)
163}
164
165pub fn keys() -> Vec<IotaKeyPair> {
166 let mut seed = StdRng::from_seed([0; 32]);
167 let kp1: IotaKeyPair = IotaKeyPair::Ed25519(get_key_pair_from_rng(&mut seed).1);
168 let kp2: IotaKeyPair = IotaKeyPair::Secp256k1(get_key_pair_from_rng(&mut seed).1);
169 let kp3: IotaKeyPair = IotaKeyPair::Secp256r1(get_key_pair_from_rng(&mut seed).1);
170
171 vec![kp1, kp2, kp3]
172}
173
174pub fn multisig_keys() -> (Ed25519PrivateKey, Secp256k1PrivateKey, Secp256r1PrivateKey) {
175 let keys = keys();
176 let kp1 = Ed25519PrivateKey::from_bytes(keys[0].to_bytes_no_flag()).unwrap();
177 let kp2 = Secp256k1PrivateKey::from_bytes(keys[1].to_bytes_no_flag()).unwrap();
178 let kp3 = Secp256r1PrivateKey::from_bytes(keys[2].to_bytes_no_flag()).unwrap();
179
180 (kp1, kp2, kp3)
181}
182
183pub fn make_upgraded_multisig_tx() -> Transaction {
184 let (kp1, kp2, kp3) = multisig_keys();
185 let pk1 = kp1.public_key();
186 let pk2 = kp2.public_key();
187 let pk3 = kp3.public_key();
188
189 let multisig_pk = MultiSigPublicKey::new(
190 vec![
191 MultisigMember::new(pk1, 1),
192 MultisigMember::new(pk2, 1),
193 MultisigMember::new(pk3, 1),
194 ],
195 2,
196 )
197 .unwrap();
198 let addr = IotaAddress::from(&multisig_pk);
199 let tx = make_transaction(addr, &SimpleKeypair::from(kp1.clone()));
200
201 let msg = IntentMessage::new(Intent::iota_transaction(), tx.transaction_data().clone())
202 .signing_digest();
203 let sig1: SimpleSignature = kp1.sign(&*msg);
204 let sig2: SimpleSignature = kp2.sign(&*msg);
205
206 let multi_sig1 = MultiSig::new(vec![sig1.into(), sig2.into()], multisig_pk).unwrap();
208 Transaction::new(SenderSignedData::new(
209 tx.transaction_data().clone(),
210 vec![GenericSignature::MultiSig(multi_sig1)],
211 ))
212}
213
214pub fn make_sponsored_regular_sig_tx() -> (Transaction, IotaAddress, IotaAddress) {
220 let (sender, sender_kp): (_, AccountKeyPair) = get_key_pair();
221 let (sponsor, sponsor_kp): (_, AccountKeyPair) = get_key_pair();
222 let tx_data = make_sponsored_transaction_data(sender, sponsor);
223 let sender_sig: GenericSignature =
224 Transaction::signature_from_signer(tx_data.clone(), Intent::iota_transaction(), &sender_kp)
225 .into();
226 let tx =
227 to_sender_signed_transaction_with_optional_sponsor(tx_data, sender_sig, Some(&sponsor_kp));
228 (tx, sender, sponsor)
229}
230
231mod move_authenticator {
232 use fastcrypto::hash::HashFunction;
233 use iota_sdk_types::Digest;
234
235 pub use crate::move_authenticator::MoveAuthenticator;
236 use crate::{
237 base_types::IotaAddress,
238 crypto::DefaultHash,
239 object::OBJECT_START_VERSION,
240 signature::GenericSignature,
241 transaction::{CallArg, SenderSignedData, SharedObjectRef, Transaction},
242 utils::{make_sponsored_transaction_data, make_transaction_data},
243 };
244
245 pub fn make_move_authenticator_tx(address: IotaAddress) -> Transaction {
247 let data = make_transaction_data(address);
248 let (authenticator, _) = make_move_authenticator_sig(address);
249 Transaction::new(SenderSignedData::new(data, vec![authenticator]))
250 }
251
252 pub fn make_move_authenticator_sig(
260 address: IotaAddress,
261 ) -> (GenericSignature, MoveAuthenticator) {
262 let authenticator = MoveAuthenticator::new_v1(
263 vec![],
264 vec![],
265 CallArg::Shared(SharedObjectRef {
266 object_id: address.into(),
267 initial_shared_version: OBJECT_START_VERSION,
268 mutable: false,
269 }),
270 );
271 let sig = GenericSignature::MoveAuthenticator(authenticator.clone());
272 (sig, authenticator)
273 }
274
275 pub fn make_sponsored_move_authenticator_tx(
282 sender_addr: IotaAddress,
283 sponsor_addr: IotaAddress,
284 ) -> (Transaction, MoveAuthenticator, MoveAuthenticator) {
285 let (sender_sig, sender_auth) = make_move_authenticator_sig(sender_addr);
286 let (sponsor_sig, sponsor_auth) = make_move_authenticator_sig(sponsor_addr);
287 let tx_data = make_sponsored_transaction_data(sender_addr, sponsor_addr);
288 let tx = Transaction::new(SenderSignedData::new(
289 tx_data,
290 vec![sender_sig, sponsor_sig],
291 ));
292 (tx, sender_auth, sponsor_auth)
293 }
294
295 pub fn blake2b256_of_sig(sig: &GenericSignature) -> Digest {
300 let mut hasher = DefaultHash::default();
301 hasher.update(sig.as_ref());
302 Digest::new(hasher.finalize().into())
303 }
304}
305
306pub use move_authenticator::*;
307
308mod passkey {
309 use fastcrypto::secp256r1::Secp256r1KeyPair;
310
311 use crate::{
312 crypto::{Signature, Signer, get_key_pair},
313 passkey_authenticator::PasskeyAuthenticator,
314 signature::GenericSignature,
315 };
316
317 pub fn make_passkey_authenticator_sig() -> GenericSignature {
324 let (_, r1_kp): (_, Secp256r1KeyPair) = get_key_pair();
325 let user_sig: Signature = r1_kp.sign(&[0u8; 32]);
326 let client_data_json = r#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","origin":"https://test.iota.org"}"#;
327 let passkey =
328 PasskeyAuthenticator::new_for_testing(vec![], client_data_json.to_string(), user_sig)
329 .unwrap();
330 GenericSignature::PasskeyAuthenticator(passkey)
331 }
332}
333
334pub use passkey::*;