From daa956219f65c85fd1f6a058ca71bde9a664d925 Mon Sep 17 00:00:00 2001 From: Marko Bencun Date: Wed, 10 Jul 2024 12:14:23 +0200 Subject: [PATCH] tests: add some cardano simulator tests --- tests/simulator_tests.rs | 2 + tests/subtests/mod.rs | 1 + tests/subtests/test_cardano.rs | 215 +++++++++++++++++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 tests/subtests/test_cardano.rs diff --git a/tests/simulator_tests.rs b/tests/simulator_tests.rs index eeef414..13d7ec4 100644 --- a/tests/simulator_tests.rs +++ b/tests/simulator_tests.rs @@ -198,6 +198,8 @@ async fn test_btc(bitbox: &PairedBitBox) { ) .unwrap(); } + + subtests::test_cardano::test(bitbox).await; } #[tokio::test] diff --git a/tests/subtests/mod.rs b/tests/subtests/mod.rs index b7a77ec..459e184 100644 --- a/tests/subtests/mod.rs +++ b/tests/subtests/mod.rs @@ -1,6 +1,7 @@ pub type PairedBitBox = bitbox_api::PairedBitBox; pub mod test_btc_psbt; +pub mod test_cardano; /// BIP32 xprv from BIP39 mnemonic used by the simulator: /// boring mistake dish oyster truth pigeon viable emerge sort crash wire portion cannon couple enact box walk height pull today solid off enable tide diff --git a/tests/subtests/test_cardano.rs b/tests/subtests/test_cardano.rs new file mode 100644 index 0000000..1ccd3bb --- /dev/null +++ b/tests/subtests/test_cardano.rs @@ -0,0 +1,215 @@ +use super::PairedBitBox; + +use bitbox_api::pb; + +pub async fn test(bitbox: &PairedBitBox) { + assert!(bitbox.cardano_supported()); + + // cardano_xpubs + { + let xpubs = bitbox + .cardano_xpubs(&[ + "m/1852'/1815'/0'".try_into().unwrap(), + "m/1852'/1815'/1'".try_into().unwrap(), + ]) + .await + .unwrap(); + assert_eq!(xpubs.len(), 2); + assert_eq!( + hex::encode(&xpubs[0]), + "9fc9550e8379cb97c2d2557d89574207c6cf4d4ff62b37e377f2b3b3c284935b677f0fe5a4a6928c7b982c0c149f140c26c0930b73c2fe16feddfa21625e0316", + ); + assert_eq!( + hex::encode(&xpubs[1]), + "7ffd0bd7d54f1648ac59a357d3eb27b878c2f7c09739d3b7c7e6662d496dea16f10ef525258833d37db047cd530bf373ebcb283495aa4c768424a2af37cee661", + ); + } + // cardano_address + { + let address = bitbox + .cardano_address( + pb::CardanoNetwork::CardanoMainnet, + &bitbox_api::cardano::make_script_config_pkh_skh( + &"m/1852'/1815'/0'/0/0".try_into().unwrap(), + &"m/1852'/1815'/0'/2/0".try_into().unwrap(), + ), + false, + ) + .await + .unwrap(); + assert_eq!( + address, + "addr1qxz808eh7aw8cwjhlxlzu4p3ct299qrzjlnp7pwvh7nc9hg0342h3nhc8vnf6c93wnxgqv3xztkfq7cnjegcqz30vg7s3sx0l4", + ); + } + + let change_config = bitbox_api::cardano::make_script_config_pkh_skh( + &"m/1852'/1815'/0'/1/0".try_into().unwrap(), + &"m/1852'/1815'/0'/2/0".try_into().unwrap(), + ); + let change_address = bitbox + .cardano_address(pb::CardanoNetwork::CardanoMainnet, &change_config, false) + .await + .unwrap(); + let keypath_input: bitbox_api::Keypath = "m/1852'/1815'/0'/0/0".try_into().unwrap(); + + // Sign a transaction with tokens + { + let transaction = pb::CardanoSignTransactionRequest { + network: pb::CardanoNetwork::CardanoMainnet as i32, + inputs: vec![ + pb::cardano_sign_transaction_request::Input { + keypath: keypath_input.to_vec(), + prev_out_hash: hex::decode("59864ee73ca5d91098a32b3ce9811bac1996dcbaefa6b6247dcaafb5779c2538").unwrap(), + prev_out_index: 0, + }, + ], + outputs: vec![ + pb::cardano_sign_transaction_request::Output { + encoded_address: "addr1q9qfllpxg2vu4lq6rnpel4pvpp5xnv3kvvgtxk6k6wp4ff89xrhu8jnu3p33vnctc9eklee5dtykzyag5penc6dcmakqsqqgpt".to_string(), + value: 1000000, + asset_groups: vec![ + // Asset policy ids and asset names from: + // https://github.com/cardano-foundation/CIPs/blob/a2ef32d8a2b485fed7f6ffde2781dd58869ff511/CIP-0014/README.md#test-vectors + pb::cardano_sign_transaction_request::AssetGroup { + policy_id: hex::decode("1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209").unwrap(), + tokens: vec![ + pb::cardano_sign_transaction_request::asset_group::Token { + asset_name: hex::decode("504154415445").unwrap(), + value: 1, + }, + pb::cardano_sign_transaction_request::asset_group::Token { + asset_name: hex::decode("7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373").unwrap(), + value: 3, + }, + ], + }, + ], + ..Default::default() + }, + pb::cardano_sign_transaction_request::Output { + encoded_address: change_address.clone(), + value: 4829501, + script_config: Some(change_config.clone()), + ..Default::default() + }, + ], + fee: 170499, + ttl: 41115811, + certificates: vec![], + withdrawals: vec![], + validity_interval_start: 41110811, + allow_zero_ttl: false, + }; + + let witness = bitbox.cardano_sign_transaction(transaction).await.unwrap(); + assert_eq!(witness.shelley_witnesses.len(), 1); + assert_eq!( + hex::encode(&witness.shelley_witnesses[0].public_key), + "6b5d4134cfc66281827d51cb0196f1a951ce168c19ba1314233f43d39d91e2bc", + ); + } + // Delegating to a staking pool... + { + let transaction = pb::CardanoSignTransactionRequest { + network: pb::CardanoNetwork::CardanoMainnet as i32, + inputs: vec![pb::cardano_sign_transaction_request::Input { + keypath: keypath_input.to_vec(), + prev_out_hash: hex::decode( + "59864ee73ca5d91098a32b3ce9811bac1996dcbaefa6b6247dcaafb5779c2538", + ) + .unwrap(), + prev_out_index: 0, + }], + outputs: vec![pb::cardano_sign_transaction_request::Output { + encoded_address: change_address.clone(), + value: 2741512, + script_config: Some(change_config.clone()), + ..Default::default() + }], + fee: 191681, + ttl: 41539125, + certificates: vec![ + pb::cardano_sign_transaction_request::Certificate { + cert: Some( + pb::cardano_sign_transaction_request::certificate::Cert::StakeRegistration( + pb::Keypath { + keypath: vec![2147485500, 2147485463, 2147483648, 2, 0], + }, + ), + ), + }, + pb::cardano_sign_transaction_request::Certificate { + cert: Some( + pb::cardano_sign_transaction_request::certificate::Cert::StakeDelegation( + pb::cardano_sign_transaction_request::certificate::StakeDelegation { + keypath: vec![2147485500, 2147485463, 2147483648, 2, 0], + pool_keyhash: hex::decode( + "abababababababababababababababababababababababababababab", + ) + .unwrap(), + }, + ), + ), + }, + ], + withdrawals: vec![], + validity_interval_start: 41110811, + allow_zero_ttl: false, + }; + + let witness = bitbox.cardano_sign_transaction(transaction).await.unwrap(); + assert_eq!(witness.shelley_witnesses.len(), 2); + assert_eq!( + hex::encode(&witness.shelley_witnesses[0].public_key), + "6b5d4134cfc66281827d51cb0196f1a951ce168c19ba1314233f43d39d91e2bc", + ); + assert_eq!( + hex::encode(&witness.shelley_witnesses[1].public_key), + "ed0d6426efcae3b02b963db0997845ba43ed53c131aa2f0faa01976ddcdb3751", + ); + } + // Withdrawing staking rewards... + { + let transaction = pb::CardanoSignTransactionRequest { + network: pb::CardanoNetwork::CardanoMainnet as i32, + inputs: vec![pb::cardano_sign_transaction_request::Input { + keypath: keypath_input.to_vec(), + prev_out_hash: hex::decode( + "59864ee73ca5d91098a32b3ce9811bac1996dcbaefa6b6247dcaafb5779c2538", + ) + .unwrap(), + prev_out_index: 0, + }], + outputs: vec![pb::cardano_sign_transaction_request::Output { + encoded_address: change_address.clone(), + value: 4817591, + script_config: Some(change_config.clone()), + ..Default::default() + }], + fee: 175157, + ttl: 41788708, + certificates: vec![], + withdrawals: vec![pb::cardano_sign_transaction_request::Withdrawal { + keypath: { + let kp: bitbox_api::Keypath = "m/1852'/1815'/0'/2/0".try_into().unwrap(); + kp.to_vec() + }, + value: 1234567, + }], + validity_interval_start: 0, + allow_zero_ttl: false, + }; + + let witness = bitbox.cardano_sign_transaction(transaction).await.unwrap(); + assert_eq!(witness.shelley_witnesses.len(), 2); + assert_eq!( + hex::encode(&witness.shelley_witnesses[0].public_key), + "6b5d4134cfc66281827d51cb0196f1a951ce168c19ba1314233f43d39d91e2bc", + ); + assert_eq!( + hex::encode(&witness.shelley_witnesses[1].public_key), + "ed0d6426efcae3b02b963db0997845ba43ed53c131aa2f0faa01976ddcdb3751", + ); + } +}