diff --git a/base_layer/wallet_ffi/src/lib.rs b/base_layer/wallet_ffi/src/lib.rs index 62ed8fd9e5..6001679ac2 100644 --- a/base_layer/wallet_ffi/src/lib.rs +++ b/base_layer/wallet_ffi/src/lib.rs @@ -163,13 +163,21 @@ use tari_comms::{ types::CommsSecretKey, }; use tari_comms_dht::{DbConnectionUrl, DhtConfig}; -use tari_core::transactions::{tari_amount::MicroTari, transaction::OutputFeatures, types::CryptoFactories}; +use tari_core::transactions::{ + tari_amount::MicroTari, + transaction::OutputFeatures, + types::{ComSignature, CryptoFactories, PublicKey}, +}; use tari_crypto::{ - keys::{PublicKey, SecretKey}, - script::ExecutionStack, + inputs, + keys::{PublicKey as PublicKeyTrait, SecretKey}, + script, tari_utilities::ByteArray, }; -use tari_p2p::transport::{TorConfig, TransportType, TransportType::Tor}; +use tari_p2p::{ + transport::{TorConfig, TransportType, TransportType::Tor}, + Network, +}; use tari_shutdown::Shutdown; use tari_utilities::{hex, hex::Hex}; use tari_wallet::{ @@ -204,18 +212,11 @@ use tari_wallet::{ }, }, }, - util::emoji::{emoji_set, EmojiId}, - Wallet, - WalletConfig, -}; - -use tari_core::transactions::types::ComSignature; -use tari_crypto::script::TariScript; -use tari_p2p::Network; -use tari_wallet::{ types::ValidationRetryStrategy, - util::emoji::EmojiIdError, + util::emoji::{emoji_set, EmojiId, EmojiIdError}, utxo_scanner_service::utxo_scanning::UtxoScannerService, + Wallet, + WalletConfig, WalletSqlite, }; use tokio::runtime::Runtime; @@ -4523,19 +4524,17 @@ pub unsafe extern "C" fn wallet_import_utxo( CString::new("Imported UTXO").unwrap().to_str().unwrap().to_owned() }; + let public_script_key = PublicKey::from_secret_key(&(*spending_key)); match (*wallet).runtime.block_on((*wallet).wallet.import_utxo( MicroTari::from(amount), &(*spending_key).clone(), - TariScript::default(), - ExecutionStack::default(), + script!(Nop), + inputs!(public_script_key), &(*source_public_key).clone(), OutputFeatures::default(), message_string, - // TODO: Add the actual metadata signature here. ComSignature::default(), - // TODO:Add the actual script private key here. - &Default::default(), - // TODO:Add the actual script offset public keys here. + &(*spending_key).clone(), &Default::default(), )) { Ok(tx_id) => tx_id, diff --git a/integration_tests/features/WalletTransactions.feature b/integration_tests/features/WalletTransactions.feature index ab899f508a..67f801f3da 100644 --- a/integration_tests/features/WalletTransactions.feature +++ b/integration_tests/features/WalletTransactions.feature @@ -116,7 +116,31 @@ Feature: Wallet Transactions Then I wait for wallet WALLET_IMPORTED to have less than 1 uT Then I check if last imported transactions are invalid in wallet WALLET_IMPORTED -Scenario: Wallet should display all transactions made + @critical + Scenario: Wallet imports faucet UTXO + Given I have a seed node NODE + And I have 1 base nodes connected to all seed nodes + And I have wallet WALLET_A connected to all seed nodes + And I have a merge mining proxy PROXY connected to NODE and WALLET_A with default config + When I merge mine 5 blocks via PROXY + Then all nodes are at height 5 + Then I wait for wallet WALLET_A to have at least 10000000000 uT + When I have wallet WALLET_B connected to all seed nodes + And I send 1000000 uT from wallet WALLET_A to wallet WALLET_B at fee 100 + When I merge mine 5 blocks via PROXY + Then all nodes are at height 10 + Then I wait for wallet WALLET_B to have at least 1000000 uT + Then I stop wallet WALLET_B + When I have wallet WALLET_C connected to all seed nodes + Then I import WALLET_B unspent outputs as faucet outputs to WALLET_C + Then I wait for wallet WALLET_C to have at least 1000000 uT + And I send 500000 uT from wallet WALLET_C to wallet WALLET_A at fee 100 + Then wallet WALLET_C detects all transactions are at least Broadcast + When I merge mine 5 blocks via PROXY + Then all nodes are at height 15 + Then I wait for wallet WALLET_C to have at least 400000 uT + + Scenario: Wallet should display all transactions made Given I have a seed node NODE And I have 1 base nodes connected to all seed nodes And I have wallet WALLET_A connected to all seed nodes @@ -136,4 +160,4 @@ Scenario: Wallet should display all transactions made Then I wait for wallet WALLET_B to have at least 500000 uT Then I check if wallet WALLET_B has 5 transactions Then I restart wallet WALLET_B - Then I check if wallet WALLET_B has 5 transactions + Then I check if wallet WALLET_B has 5 transactions \ No newline at end of file diff --git a/integration_tests/features/support/steps.js b/integration_tests/features/support/steps.js index dd8c00fab1..2a14b8b904 100644 --- a/integration_tests/features/support/steps.js +++ b/integration_tests/features/support/steps.js @@ -453,6 +453,20 @@ When( } ); +When( + /I import (.*) unspent outputs as faucet outputs to (.*)/, + async function (walletNameA, walletNameB) { + let walletA = this.getWallet(walletNameA); + let walletB = this.getWallet(walletNameB); + let clientB = walletB.getClient(); + + await walletA.exportUnspentOutputs(); + let outputs = await walletA.readExportedOutputsAsFaucetOutputs(); + let result = await clientB.importUtxos(outputs); + lastResult = result.tx_ids; + } +); + When( /I check if last imported transactions are invalid in wallet (.*)/, async function (walletName) { diff --git a/integration_tests/helpers/walletProcess.js b/integration_tests/helpers/walletProcess.js index 80c291c407..d30a4983d6 100644 --- a/integration_tests/helpers/walletProcess.js +++ b/integration_tests/helpers/walletProcess.js @@ -7,6 +7,7 @@ const { expect } = require("chai"); const { createEnv } = require("./config"); const WalletClient = require("./walletClient"); const csvParser = require("csv-parser"); +var tari_crypto = require("tari_crypto"); let outputProcess; @@ -300,6 +301,43 @@ class WalletProcess { return unblinded_outputs; } + + // Faucet outputs are only provided with an amount and spending key so we zero out the other output data + // and update the input data to be the public key of the spending key, make the script private key the spending key + // and then we can test if this output is still spendable when imported into the wallet. + async readExportedOutputsAsFaucetOutputs() { + let outputs = await this.readExportedOutputs(); + for (let i = 0; i < outputs.length; i++) { + outputs[i].metadata_signature = { + public_nonce_commitment: Buffer.from( + "0000000000000000000000000000000000000000000000000000000000000000", + "hex" + ), + signature_u: Buffer.from( + "0000000000000000000000000000000000000000000000000000000000000000", + "hex" + ), + signature_v: Buffer.from( + "0000000000000000000000000000000000000000000000000000000000000000", + "hex" + ), + }; + outputs[i].sender_offset_public_key = Buffer.from( + "0000000000000000000000000000000000000000000000000000000000000000", + "hex" + ); + outputs[i].script_private_key = outputs[i].spending_key; + let scriptPublicKey = tari_crypto.pubkey_from_secret( + outputs[i].spending_key.toString("hex") + ); + let input_data = Buffer.concat([ + Buffer.from([0x04]), + Buffer.from(scriptPublicKey, "hex"), + ]); + outputs[i].input_data = input_data; + } + return outputs; + } } module.exports = WalletProcess;