Skip to content

Commit

Permalink
fix: update LibWallet wallet_import_utxo method to include valid Ta…
Browse files Browse the repository at this point in the history
…riScript (#3139)

## Description
The `wallet_import_utxo` FFI function in LibWallet just used defaults for a number of the new UTXO fields when importing a faucet UTXO. The Faucet UTXO provided by the client is just the spending key and amount. The `metadata_signature` and `sender_offset_public_key` can both remain as default values as they are not used in spending an UTXO.  A Nop script is assumed and the spending key is used as the `script_private_key`. The final update is that the `input_data` it set as the public key of the spending key.

To test that the base node is happy for an UTXO imported in this way to be spent a Cucumber test is provided which imports a UTXO into a wallet and zeroes out the `metadata_signature` and`sender_offset_public_key` and updates the `input_data` and `script_private_key` in the same way as described above. This imported Faucet utxo is then successfully spent to another wallet.

## How Has This Been Tested?
Cucumber test provided

## Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
* [x] I'm merging against the `development` branch.
* [x] I have squashed my commits into a single commit.
  • Loading branch information
aviator-app[bot] committed Jul 29, 2021
2 parents 0861d72 + 7d6f7a5 commit cc6de2a
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 22 deletions.
39 changes: 19 additions & 20 deletions base_layer/wallet_ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
28 changes: 26 additions & 2 deletions integration_tests/features/WalletTransactions.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
14 changes: 14 additions & 0 deletions integration_tests/features/support/steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
38 changes: 38 additions & 0 deletions integration_tests/helpers/walletProcess.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;

0 comments on commit cc6de2a

Please sign in to comment.