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,
14 crypto::{Intent, IntentMessage},
15};
16use rand::{SeedableRng, rngs::StdRng};
17
18use crate::{
19 base_types::{dbg_addr, random_object_ref},
20 committee::Committee,
21 crypto::{
22 AccountKeyPair, AuthorityKeyPair, AuthorityPublicKeyBytes, IotaKeyPair, Signature, Signer,
23 ToFromBytes as _, get_key_pair, get_key_pair_from_rng,
24 },
25 multisig::{MultiSig, MultiSigPublicKey, MultisigMember},
26 object::Object,
27 programmable_transaction_builder::ProgrammableTransactionBuilder,
28 signature::GenericSignature,
29 transaction::{
30 SenderSignedData, TEST_ONLY_GAS_UNIT_FOR_TRANSFER, Transaction, TransactionData,
31 TransactionDataAPI,
32 },
33};
34
35pub fn make_committee_key<R>(rand: &mut R) -> (Vec<AuthorityKeyPair>, Committee)
36where
37 R: rand::CryptoRng + rand::RngCore,
38{
39 make_committee_key_num(4, rand)
40}
41
42pub fn make_committee_key_num<R>(num: usize, rand: &mut R) -> (Vec<AuthorityKeyPair>, Committee)
43where
44 R: rand::CryptoRng + rand::RngCore,
45{
46 let mut authorities: BTreeMap<AuthorityPublicKeyBytes, u64> = BTreeMap::new();
47 let mut keys = Vec::new();
48
49 for _ in 0..num {
50 let (_, inner_authority_key): (_, AuthorityKeyPair) = get_key_pair_from_rng(rand);
51 authorities.insert(
52 AuthorityPublicKeyBytes::from(inner_authority_key.public()),
54 1,
56 );
57 keys.push(inner_authority_key);
58 }
59
60 let committee = Committee::new_for_testing_with_normalized_voting_power(0, authorities);
61 (keys, committee)
62}
63
64pub fn create_fake_transaction() -> Transaction {
67 let (sender, sender_key): (_, AccountKeyPair) = get_key_pair();
68 let recipient = dbg_addr(2);
69 let object_id = ObjectId::random();
70 let object = Object::immutable_with_id_for_testing(object_id);
71 let pt = {
72 let mut builder = ProgrammableTransactionBuilder::new();
73 builder.transfer_iota(recipient, None);
74 builder.finish()
75 };
76 let data = TransactionData::new_programmable(
77 sender,
78 vec![object.object_ref()],
79 pt,
80 TEST_ONLY_GAS_UNIT_FOR_TRANSFER, 1,
82 );
83 to_sender_signed_transaction(data, &sender_key)
84}
85
86pub fn make_transaction_data(sender: Address) -> TransactionData {
87 let object =
88 Object::immutable_with_id_for_testing(ObjectId::generate(StdRng::from_seed([0; 32])));
89 let pt = {
90 let mut builder = ProgrammableTransactionBuilder::new();
91 builder.transfer_iota(dbg_addr(2), None);
92 builder.finish()
93 };
94 TransactionData::new_programmable(
95 sender,
96 vec![object.object_ref()],
97 pt,
98 TEST_ONLY_GAS_UNIT_FOR_TRANSFER, 1,
100 )
101}
102
103pub fn make_sponsored_transaction_data(sender: Address, sponsor: Address) -> TransactionData {
106 let pt = {
107 let mut builder = ProgrammableTransactionBuilder::new();
108 builder.transfer_iota(dbg_addr(2), None);
109 builder.finish()
110 };
111 TransactionData::new_with_gas_coins_allow_sponsor(
112 TransactionKind::new_programmable(pt),
113 sender,
114 vec![random_object_ref()],
115 TEST_ONLY_GAS_UNIT_FOR_TRANSFER, 1,
117 sponsor,
118 )
119}
120
121pub fn make_transaction(sender: Address, kp: &SimpleKeypair) -> Transaction {
124 let data = make_transaction_data(sender);
125 let kp = IotaKeyPair::from_bytes(&kp.to_bytes()).unwrap();
127 Transaction::from_data_and_signer(data, vec![&kp])
128}
129
130pub fn to_sender_signed_transaction(
132 data: TransactionData,
133 signer: &dyn Signer<Signature>,
134) -> Transaction {
135 to_sender_signed_transaction_with_multi_signers(data, vec![signer])
136}
137
138pub fn to_sender_signed_transaction_with_optional_sponsor(
139 data: TransactionData,
140 sender_signature: GenericSignature,
141 sponsor_signer_opt: Option<&dyn Signer<Signature>>,
142) -> Transaction {
143 let mut signatures = vec![sender_signature];
144 if let Some(sponsor) = sponsor_signer_opt {
145 let sponsor_sig =
146 Transaction::signature_from_signer(data.clone(), Intent::iota_transaction(), sponsor)
147 .into();
148 signatures.push(sponsor_sig);
149 };
150
151 Transaction::from_generic_sig_data(data, signatures)
152}
153
154pub fn to_sender_signed_transaction_with_multi_signers(
155 data: TransactionData,
156 signers: Vec<&dyn Signer<Signature>>,
157) -> Transaction {
158 Transaction::from_data_and_signer(data, signers)
159}
160
161pub fn keys() -> Vec<IotaKeyPair> {
162 let mut seed = StdRng::from_seed([0; 32]);
163 let kp1: IotaKeyPair = IotaKeyPair::Ed25519(get_key_pair_from_rng(&mut seed).1);
164 let kp2: IotaKeyPair = IotaKeyPair::Secp256k1(get_key_pair_from_rng(&mut seed).1);
165 let kp3: IotaKeyPair = IotaKeyPair::Secp256r1(get_key_pair_from_rng(&mut seed).1);
166
167 vec![kp1, kp2, kp3]
168}
169
170pub fn multisig_keys() -> (Ed25519PrivateKey, Secp256k1PrivateKey, Secp256r1PrivateKey) {
171 let keys = keys();
172 let kp1 = Ed25519PrivateKey::from_bytes(keys[0].to_bytes_no_flag()).unwrap();
173 let kp2 = Secp256k1PrivateKey::from_bytes(keys[1].to_bytes_no_flag()).unwrap();
174 let kp3 = Secp256r1PrivateKey::from_bytes(keys[2].to_bytes_no_flag()).unwrap();
175
176 (kp1, kp2, kp3)
177}
178
179pub fn make_upgraded_multisig_tx() -> Transaction {
180 let (kp1, kp2, kp3) = multisig_keys();
181 let pk1 = kp1.public_key();
182 let pk2 = kp2.public_key();
183 let pk3 = kp3.public_key();
184
185 let multisig_pk = MultiSigPublicKey::new(
186 vec![
187 MultisigMember::new(pk1, 1),
188 MultisigMember::new(pk2, 1),
189 MultisigMember::new(pk3, 1),
190 ],
191 2,
192 )
193 .unwrap();
194 let addr = Address::from(&multisig_pk);
195 let tx = make_transaction(addr, &SimpleKeypair::from(kp1.clone()));
196
197 let msg = IntentMessage::new(Intent::iota_transaction(), tx.transaction_data().clone())
198 .signing_digest();
199 let sig1: SimpleSignature = kp1.sign(&*msg);
200 let sig2: SimpleSignature = kp2.sign(&*msg);
201
202 let multi_sig1 = MultiSig::new(vec![sig1.into(), sig2.into()], multisig_pk).unwrap();
204 Transaction::new(SenderSignedData::new(
205 tx.transaction_data().clone(),
206 vec![GenericSignature::MultiSig(multi_sig1)],
207 ))
208}
209
210pub fn make_sponsored_regular_sig_tx() -> (Transaction, Address, Address) {
216 let (sender, sender_kp): (_, AccountKeyPair) = get_key_pair();
217 let (sponsor, sponsor_kp): (_, AccountKeyPair) = get_key_pair();
218 let tx_data = make_sponsored_transaction_data(sender, sponsor);
219 let sender_sig: GenericSignature =
220 Transaction::signature_from_signer(tx_data.clone(), Intent::iota_transaction(), &sender_kp)
221 .into();
222 let tx =
223 to_sender_signed_transaction_with_optional_sponsor(tx_data, sender_sig, Some(&sponsor_kp));
224 (tx, sender, sponsor)
225}
226
227mod move_authenticator {
228 use fastcrypto::hash::HashFunction;
229 use iota_sdk_types::{Address, Digest, SharedObjectReference};
230
231 pub use crate::move_authenticator::{MoveAuthenticator, MoveAuthenticatorV1};
232 use crate::{
233 crypto::DefaultHash,
234 object::OBJECT_START_VERSION,
235 signature::GenericSignature,
236 transaction::{SenderSignedData, Transaction},
237 utils::{make_sponsored_transaction_data, make_transaction_data},
238 };
239
240 pub fn make_move_authenticator_tx(address: Address) -> Transaction {
242 let data = make_transaction_data(address);
243 let (authenticator, _) = make_move_authenticator_sig(address);
244 Transaction::new(SenderSignedData::new(data, vec![authenticator]))
245 }
246
247 pub fn make_move_authenticator_sig(address: Address) -> (GenericSignature, MoveAuthenticator) {
255 let authenticator =
256 MoveAuthenticator::from(MoveAuthenticatorV1::new_with_shared_account_object(
257 vec![],
258 vec![],
259 SharedObjectReference::new(address.into(), OBJECT_START_VERSION, false),
260 ));
261 let sig = GenericSignature::MoveAuthenticator(authenticator.clone());
262 (sig, authenticator)
263 }
264
265 pub fn make_sponsored_move_authenticator_tx(
272 sender_addr: Address,
273 sponsor_addr: Address,
274 ) -> (Transaction, MoveAuthenticator, MoveAuthenticator) {
275 let (sender_sig, sender_auth) = make_move_authenticator_sig(sender_addr);
276 let (sponsor_sig, sponsor_auth) = make_move_authenticator_sig(sponsor_addr);
277 let tx_data = make_sponsored_transaction_data(sender_addr, sponsor_addr);
278 let tx = Transaction::new(SenderSignedData::new(
279 tx_data,
280 vec![sender_sig, sponsor_sig],
281 ));
282 (tx, sender_auth, sponsor_auth)
283 }
284
285 pub fn blake2b256_of_sig(sig: &GenericSignature) -> Digest {
290 let mut hasher = DefaultHash::default();
291 hasher.update(sig.to_bytes());
292 Digest::new(hasher.finalize().into())
293 }
294}
295
296pub use move_authenticator::*;
297
298mod passkey {
299 use fastcrypto::secp256r1::Secp256r1KeyPair;
300
301 use super::*;
302 use crate::{
303 crypto::{Signature, Signer, get_key_pair},
304 passkey_authenticator::PasskeyAuthenticator,
305 signature::GenericSignature,
306 };
307
308 pub fn make_passkey_authenticator_sig() -> GenericSignature {
315 let (_, r1_kp): (_, Secp256r1KeyPair) = get_key_pair();
316 let user_sig: Signature = r1_kp.sign(&[0u8; 32]);
317 let client_data_json = r#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","origin":"https://test.iota.org"}"#;
318 let passkey = PasskeyAuthenticator::new(
319 vec![],
320 client_data_json.to_string(),
321 SimpleSignature::from_bytes(user_sig.as_bytes()).unwrap(),
322 )
323 .unwrap();
324 GenericSignature::PasskeyAuthenticator(passkey)
325 }
326}
327
328pub use passkey::*;