mirror of https://github.com/oxen-io/oxen-core.git
Loads in real data to test if the transaction is signing correctly
The wallet needs to be fed a single output plus a sufficient number of decoys. This transaction was run on the testnet and details were copied into the test file.
This commit is contained in:
parent
eb8f4a51a6
commit
b1d4921e24
|
@ -32,6 +32,7 @@ namespace wallet
|
|||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
block INTEGER NOT NULL REFERENCES blocks(height) ON DELETE CASCADE,
|
||||
hash TEXT NOT NULL,
|
||||
public_key TEXT NOT NULL,
|
||||
UNIQUE(hash)
|
||||
);
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ namespace wallet
|
|||
std::vector<int64_t>
|
||||
DecoySelector::operator()(const Output& selected_output)
|
||||
{
|
||||
std::vector<Decoy> return_decoys;
|
||||
const size_t n_decoys = 13;
|
||||
|
||||
// Select some random outputs according to gamma distribution
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace wallet
|
|||
class DecoySelector
|
||||
{
|
||||
public:
|
||||
std::vector<int64_t>
|
||||
virtual std::vector<int64_t>
|
||||
operator()(const Output& selected_output);
|
||||
|
||||
DecoySelector(int64_t min, int64_t max) : min_output_index(min), max_output_index(max) {};
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace wallet
|
|||
int64_t spent_time;
|
||||
|
||||
crypto::hash tx_hash;
|
||||
crypto::public_key tx_public_key;
|
||||
crypto::public_key key;
|
||||
crypto::key_derivation derivation;
|
||||
rct::key rct_mask;
|
||||
|
|
|
@ -2,15 +2,19 @@
|
|||
#include "pending_transaction.hpp"
|
||||
#include "decoy.hpp"
|
||||
#include "output_selection/output_selection.hpp"
|
||||
<<<<<<< HEAD
|
||||
#include "decoy_selection/decoy_selection.hpp"
|
||||
#include "db_schema.hpp"
|
||||
=======
|
||||
#include <sqlitedb/database.hpp>
|
||||
>>>>>>> Loads in real data to test if the transaction is signing correctly
|
||||
|
||||
namespace wallet
|
||||
{
|
||||
// create_transaction will create a vanilla spend transaction without any special features.
|
||||
PendingTransaction
|
||||
TransactionConstructor::create_transaction(
|
||||
const std::vector<cryptonote::tx_destination_entry>& recipients) const
|
||||
const std::vector<cryptonote::tx_destination_entry>& recipients)
|
||||
{
|
||||
PendingTransaction new_tx(recipients);
|
||||
new_tx.fee_per_byte = fee_per_byte;
|
||||
|
@ -65,7 +69,7 @@ namespace wallet
|
|||
// details necessary for a ring signature from teh daemon and add them to the
|
||||
// transaction ready to sign at a later point in time.
|
||||
void
|
||||
TransactionConstructor::select_and_fetch_decoys(PendingTransaction& ptx) const
|
||||
TransactionConstructor::select_and_fetch_decoys(PendingTransaction& ptx)
|
||||
{
|
||||
ptx.decoys = {};
|
||||
// This initialises the decoys to be selected from global_output_index= 0 to global_output_index = highest_output_index
|
||||
|
@ -74,7 +78,7 @@ namespace wallet
|
|||
std::vector<int64_t> indexes;
|
||||
for (const auto& output : ptx.chosen_outputs)
|
||||
{
|
||||
indexes = decoy_selection(output);
|
||||
indexes = (*decoy_selector)(output);
|
||||
auto decoy_promise = daemon->fetch_decoys(indexes);
|
||||
decoy_promise.wait();
|
||||
ptx.decoys.emplace_back(decoy_promise.get());
|
||||
|
@ -82,7 +86,7 @@ namespace wallet
|
|||
}
|
||||
|
||||
void
|
||||
TransactionConstructor::select_inputs_and_finalise(PendingTransaction& ptx) const
|
||||
TransactionConstructor::select_inputs_and_finalise(PendingTransaction& ptx)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "address.hpp"
|
||||
#include "pending_transaction.hpp"
|
||||
#include "daemon_comms.hpp"
|
||||
#include "decoy_selection/decoy_selection.hpp"
|
||||
|
||||
namespace wallet
|
||||
{
|
||||
|
@ -15,26 +16,38 @@ namespace wallet
|
|||
{
|
||||
public:
|
||||
TransactionConstructor(std::shared_ptr<WalletDB> database, std::shared_ptr<DaemonComms> dmn)
|
||||
: db(std::move(database)), daemon(std::move(dmn))
|
||||
: db(std::move(database)), daemon(std::move(dmn)), decoy_selector(std::make_unique<DecoySelector>(0,0))
|
||||
{
|
||||
std::tie(fee_per_byte, fee_per_output) = daemon->get_fee_parameters();
|
||||
|
||||
// This initialises the decoys to be selected from global_output_index= 0 to global_output_index = highest_output_index
|
||||
// Oxen started with ringct transaction from its genesis so all transactions should be usable as decoys.
|
||||
// We keep track of the number of transactions in each block so we can recreate the highest_output_index by summing
|
||||
// all the transactions in every block.
|
||||
|
||||
// TODO sean this should actually be kept track of somewhere in the schema. not just max of *our* outputs
|
||||
//int64_t max_output_index = db->prepared_get<int>("SELECT max(global_index) FROM outputs;");
|
||||
int64_t max_output_index = 100;
|
||||
decoy_selector = std::make_unique<DecoySelector>(0, max_output_index);
|
||||
};
|
||||
|
||||
PendingTransaction
|
||||
create_transaction(const std::vector<cryptonote::tx_destination_entry>& recipients) const;
|
||||
create_transaction(const std::vector<cryptonote::tx_destination_entry>& recipients);
|
||||
|
||||
uint64_t fee_per_byte = FEE_PER_BYTE_V13;
|
||||
uint64_t fee_per_output = FEE_PER_OUTPUT_V18;
|
||||
|
||||
std::unique_ptr<DecoySelector> decoy_selector;
|
||||
|
||||
private:
|
||||
void
|
||||
select_inputs(PendingTransaction& ptx) const;
|
||||
|
||||
void
|
||||
select_and_fetch_decoys(PendingTransaction& ptx) const;
|
||||
select_and_fetch_decoys(PendingTransaction& ptx);
|
||||
|
||||
void
|
||||
select_inputs_and_finalise(PendingTransaction& ptx) const;
|
||||
select_inputs_and_finalise(PendingTransaction& ptx);
|
||||
|
||||
int64_t
|
||||
estimate_fee() const;
|
||||
|
|
|
@ -75,6 +75,7 @@ namespace wallet
|
|||
o.output_index = output_index;
|
||||
o.global_index = tx.global_indices[output_index];
|
||||
o.tx_hash = tx.hash;
|
||||
o.tx_public_key = tx_public_keys[0];
|
||||
o.block_height = height;
|
||||
o.block_time = timestamp;
|
||||
o.unlock_time = tx.tx.get_unlock_time(output_index);
|
||||
|
|
|
@ -11,6 +11,8 @@ class MockDaemonComms: public DefaultDaemonComms
|
|||
|
||||
MockDaemonComms() : DefaultDaemonComms(get_omq()){};
|
||||
|
||||
std::vector<Decoy> predetermined_decoys;
|
||||
|
||||
std::shared_ptr<oxenmq::OxenMQ> get_omq() {
|
||||
return std::make_shared<oxenmq::OxenMQ>();
|
||||
}
|
||||
|
@ -27,11 +29,27 @@ class MockDaemonComms: public DefaultDaemonComms
|
|||
|
||||
std::vector<Decoy> returned_decoys;
|
||||
for (auto index : indexes)
|
||||
returned_decoys.push_back(Decoy{index, "","","",true});
|
||||
{
|
||||
//std::cout << __FILE__ << ":" << __LINE__ << " (" << __func__ << ") TODO sean remove this - index: " << index << " - debug\n";
|
||||
auto it = std::find_if(predetermined_decoys.begin(), predetermined_decoys.end(), [index](const auto& decoy) { return decoy.global_index == index; });
|
||||
if (it != predetermined_decoys.end())
|
||||
returned_decoys.push_back(*it);
|
||||
else
|
||||
returned_decoys.push_back(Decoy{0, "","","",true, index});
|
||||
}
|
||||
|
||||
p.set_value(returned_decoys);
|
||||
return fut;
|
||||
}
|
||||
|
||||
void
|
||||
add_decoy(std::string_view public_key, uint64_t global_index)
|
||||
{
|
||||
wallet::Decoy decoy{};
|
||||
tools::hex_to_type(public_key, decoy.key);
|
||||
decoy.global_index = global_index;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
|
||||
#include <wallet3/decoy_selection/decoy_selection.hpp>
|
||||
|
||||
namespace wallet
|
||||
{
|
||||
class MockDecoySelector: public DecoySelector
|
||||
{
|
||||
|
||||
public:
|
||||
MockDecoySelector() : DecoySelector(0,0) {}
|
||||
|
||||
std::vector<int64_t> predetermined_indexes;
|
||||
int64_t last_index = 0;
|
||||
|
||||
virtual std::vector<int64_t>
|
||||
operator()(const Output& selected_output) override
|
||||
{
|
||||
const size_t n_decoys = 13;
|
||||
std::vector<int64_t> decoy_indexes;
|
||||
for (size_t i = 0; i < n_decoys; ++i)
|
||||
{
|
||||
decoy_indexes.push_back(predetermined_indexes[last_index]);
|
||||
if (last_index + 1 == static_cast<int64_t>(decoy_indexes.size()))
|
||||
last_index = 0;
|
||||
else
|
||||
last_index++;
|
||||
}
|
||||
return decoy_indexes;
|
||||
}
|
||||
|
||||
void
|
||||
add_index(const std::vector<int64_t>& indices)
|
||||
{
|
||||
predetermined_indexes.insert(predetermined_indexes.end(), indices.begin(), indices.end());
|
||||
}
|
||||
|
||||
};
|
||||
} // namespace wallet
|
|
@ -9,6 +9,9 @@
|
|||
#include "mock_wallet.hpp"
|
||||
#include "mock_keyring.hpp"
|
||||
#include "mock_daemon_comms.hpp"
|
||||
#include "mock_decoy_selector.hpp"
|
||||
|
||||
#include <oxenmq/hex.h>
|
||||
|
||||
|
||||
TEST_CASE("Transaction Creation", "[wallet,tx]")
|
||||
|
@ -118,9 +121,32 @@ TEST_CASE("Transaction Creation", "[wallet,tx]")
|
|||
{
|
||||
// Start a new wallet for real inputs to test signatures
|
||||
auto wallet_with_valid_inputs = wallet::MockWallet();
|
||||
auto ctor_for_signing = wallet::TransactionConstructor(wallet_with_valid_inputs.get_db(), comms);
|
||||
|
||||
auto comms_with_decoys = std::make_shared<wallet::MockDaemonComms>();
|
||||
comms_with_decoys.add_decoy("37d660205a18fb91debe5b73911e30ed2d353a0b611e89cf20a110653b3d39377ad740731e5b26a0f1e87f3fc0702865196b9a58dccf7d7fc47e721f6a9837b0", 894631);
|
||||
comms_with_decoys.add_decoy("0c86e47e52bed3925cd9dc56052279af96e26b18741bae79ae86e019bac0fdc07ad740731e5b26a0f1e87f3fc0702865196b9a58dccf7d7fc47e721f6a9837b0", 1038224);
|
||||
comms_with_decoys.add_decoy("a44418c0eaf4f295092b5be2bdfc6a8a7e78d57e2fe3f1a0af267a8a2a451fd17ad740731e5b26a0f1e87f3fc0702865196b9a58dccf7d7fc47e721f6a9837b0", 1049882);
|
||||
comms_with_decoys.add_decoy("590bcaf258e68c79620e9a0b62d81ff2b4cbd19001d4764b76f17d8fceeff8e77ad740731e5b26a0f1e87f3fc0702865196b9a58dccf7d7fc47e721f6a9837b0", 1093414);
|
||||
comms_with_decoys.add_decoy("460f88c45744fc4b78f7df046a9bf254194fceac1074dc9674a54ee41d4baf477ad740731e5b26a0f1e87f3fc0702865196b9a58dccf7d7fc47e721f6a9837b0", 1093914);
|
||||
comms_with_decoys.add_decoy("f075807f61c902e65b2b0f6ea817699c8dd291b060284a77c890586632da42637ad740731e5b26a0f1e87f3fc0702865196b9a58dccf7d7fc47e721f6a9837b0", 1094315);
|
||||
comms_with_decoys.add_decoy("87b2d9b0550a72781b75d190096ffd7e9a5bb15b9f22652f042135fbf7a353187ad740731e5b26a0f1e87f3fc0702865196b9a58dccf7d7fc47e721f6a9837b0", 1094323);
|
||||
comms_with_decoys.add_decoy("5e549f2f3f67cc369cb4387fdee18c5bfde2917e4157aee2cb9129b02f3aafe07ad740731e5b26a0f1e87f3fc0702865196b9a58dccf7d7fc47e721f6a9837b0", 1094368);
|
||||
comms_with_decoys.add_decoy("48a8ff99d1bb51271d2fc3bfbf6af754dc16835a7ba1993ddeadbe1a77efd15b7ad740731e5b26a0f1e87f3fc0702865196b9a58dccf7d7fc47e721f6a9837b0", 1094881);
|
||||
comms_with_decoys.add_decoy("02c6cf65059a02844ca0e7442687d704a0806f055a1e8e0032cd07e1d08885b27ad5bc62d68270ae3e5879ed425603e6b1534328f4419ad84b8c8077f9221721", 1094887); // Real Output
|
||||
|
||||
auto ctor_for_signing = wallet::TransactionConstructor(wallet_with_valid_inputs.get_db(), comms_with_decoys);
|
||||
|
||||
auto decoy_selector = std::make_unique<wallet::MockDecoySelector>();
|
||||
decoy_selector->add_index({894631, 1038224, 1049882, 1093414, 1093914, 1094315, 1094323, 1094368, 1094881, 1094887});
|
||||
ctor_for_signing.decoy_selector = std::move(decoy_selector);
|
||||
|
||||
wallet::Output o{};
|
||||
o.amount = 1000000000000;
|
||||
tools::hex_to_type("3bf997b70d9a26e60525f1b14d0383f08c3ec0559aaf7639827d08214d6aa664", o.tx_public_key);
|
||||
tools::hex_to_type("02c6cf65059a02844ca0e7442687d704a0806f055a1e8e0032cd07e1d08885b27ad5bc62d68270ae3e5879ed425603e6b1534328f4419ad84b8c8077f9221721", o.key); // Public Key of Output
|
||||
tools::hex_to_type("145209bdaf35087c0e61daa14a9b7d3fe3a3c14fc266724d3e7c38cd0b43a201", o.rct_mask);
|
||||
tools::hex_to_type("1b6e1e63b1b634c6faaad8eb23f273f98b4b7cedb0a449f8d25c7eea2361d458", o.key_image);
|
||||
o.subaddress_index = cryptonote::subaddress_index{0,0};
|
||||
|
||||
wallet_with_valid_inputs.store_test_output(o);
|
||||
std::vector<cryptonote::tx_destination_entry> recipients;
|
||||
|
@ -132,5 +158,107 @@ TEST_CASE("Transaction Creation", "[wallet,tx]")
|
|||
auto keys = std::make_unique<wallet::MockKeyring>();
|
||||
REQUIRE_NOTHROW(keys->sign_transaction(ptx));
|
||||
auto& signedtx = ptx.tx;
|
||||
for (const auto& decoys : ptx.decoys)
|
||||
{
|
||||
REQUIRE(decoys.size() == 13);
|
||||
}
|
||||
|
||||
//Final Transaction should look like this
|
||||
//{ "version": 4, "output_unlock_times": [ 0, 0 ], "unlock_time": 0,
|
||||
//"vin": [
|
||||
//{
|
||||
//"key": {
|
||||
//"amount": 0,
|
||||
//"key_offsets": [ 894631, 143593, 11658, 43532, 500, 401, 8, 45, 513, 6 ],
|
||||
//"k_image": "1b6e1e63b1b634c6faaad8eb23f273f98b4b7cedb0a449f8d25c7eea2361d458"
|
||||
//}
|
||||
//}
|
||||
//],
|
||||
//"vout": [
|
||||
//{
|
||||
//"amount": 0,
|
||||
//"target": {
|
||||
//"key": "f2c6c7a593ad18a0643715b5eb0acab137a5a3670a67a082a508e55e756fe20f"
|
||||
//}
|
||||
//},
|
||||
//{
|
||||
//"amount": 0,
|
||||
//"target": {
|
||||
//"key": "c9b304a61fa66328867dde512dc1cd6a4a1364a17aaf01c994995c0767e28f2e"
|
||||
//}
|
||||
//}
|
||||
//],
|
||||
//"extra": [ 1, 242, 7, 2, 187, 108, 154, 15, 107, 44, 180, 120, 108, 9, 214, 19, 184, 83, 191, 255, 114, 112, 219, 81, 147, 135, 119, 231, 239, 7, 32, 218, 225, 2, 9, 1, 186, 35, 240, 225, 57, 168, 234, 151, 121, 52, 123, 54, 1, 0, 0, 0, 0 ],
|
||||
//"type": 0,
|
||||
//"rct_signatures": {
|
||||
//"type": 5,
|
||||
//"txnFee": 30521550,
|
||||
//"ecdhInfo": [ {
|
||||
//"amount": "d3bde6f24db5ed4d"
|
||||
//}, {
|
||||
//"amount": "94eb0dd9f3603958"
|
||||
//}
|
||||
//],
|
||||
//"outPk": [
|
||||
//"af85ed6e314c56c493d6e8bd796fe1023a6b94777ab98b5ee6ffc219b097e932",
|
||||
//"12baf689c9850b215bb99e518852ba5c5fea08cb5471e588c3fd5069161f5ef2"
|
||||
//]
|
||||
//},
|
||||
//"rctsig_prunable": {
|
||||
//"nbp": 1,
|
||||
//"bp": [
|
||||
//{
|
||||
//"A": "c62bdd0f1a485be62b1a415aa7ae783298c06f1e77c2cabe3b919521e587ed82",
|
||||
//"S": "efe0cf9004a20eea2478e4316769fe24d2eff8748d0baefc36fd833b709c5f8e",
|
||||
//"T1": "69972f474aebb0f83efe4c1fa6545b5036c7218f80eac34a827a5034b979f2c9",
|
||||
//"T2": "8fe78eadafe8b4f0764ea61ddf60a3502430a31cb82e4e48925120f51486f0e9",
|
||||
//"taux": "80d452180ff66a7c223669821715811e8bd15b0ff5b2033eeaa6ad4d67ed850d",
|
||||
//"mu": "767a55060bc1a22015be604abae36b5e21d45e863b400d5ecd1e8ad9b83f2101",
|
||||
//"L": [
|
||||
//"c352794bd966d436163f31b58523cd8209db8da630398fc5cc28ed2f9240ada7",
|
||||
//"cf8ce0c1b7d5de50a93996a0548595bd71f16830a66b3cddaafc0df390f3cf1b",
|
||||
//"ed2dfabd819aaf4dffd63de9c6e5f0f91912a9155e4aaedae2a5641320bac65e",
|
||||
//"9fd4451b6e9059873b2780acf666a55a24574f2229b6598f6d4cb18ccb49bf19",
|
||||
//"33e20f36f747f4047075fd705d84ffde562053c47e47b83fed77b0c6f7c9bbc9",
|
||||
//"e67293e4220182f2b09ea5c07516abac794ce614af7313dd2e72ec18b609750e",
|
||||
//"bcf87f8344052864935039074bf97ce90cfb0d49446866aa796c0366bd76a668"
|
||||
//],
|
||||
//"R": [
|
||||
//"dc0450f5f66fc961019ca4270c536ccfb07add9d8ee37d0f0abff00d0c756e88",
|
||||
//"046c4d0adb40e3abc658fb227d32876a76ef401859d4508484dc2b52e6c03ecf",
|
||||
//"7b1b97765c2cc73de71cf07ec12c959c4ab4ccadc0e683b0d6abadf0e208fdfe",
|
||||
//"b8418c1a63fe049bb79b1a0dc7879b4f55e7cd20a9f0c5f84ea8ee15f73eae52",
|
||||
//"eb3a456197ae0b027220a0dc0b04f52032d991a5cf7f4e82a18772e12cfa1895",
|
||||
//"3cc43eceb758d0e78048c9f403319286a248009ca6027b2acad918a312ce9a1f",
|
||||
//"1b912deece231eb682df659f549709f5e958e46e23c47b876eac54ae977376a6"
|
||||
//],
|
||||
//"a": "efc8c93275bf099740f787d2318e240580ef1119abe6af927dd5c6ba722ab705",
|
||||
//"b": "87b84102500af01ebf71c701ff1aec6a408e54d2995f362011e09abdd5d98b01",
|
||||
//"t": "5b6c4e70f8932bef5344b32840f22453aca1e02496a084e9686d4aec52eb970e"
|
||||
//}
|
||||
//],
|
||||
//"CLSAGs": [
|
||||
//{
|
||||
//"s": [
|
||||
//"69823d1c3774eef1bfbfe82fab65f5633cb90e9ea907c9e8a005757e49ffa201",
|
||||
//"b791b1bb685238bb8d29d4902d4806253bedb0232da140696315d7951a204206",
|
||||
//"3c4159a04f441f91dcb277d450cdeb4e1ccf51983c2e5c52b15e365bdecf270b",
|
||||
//"ae56963b0576c6d6053d0a2e98a2db799f89d0d593fa3cf508a3bed461d44d03",
|
||||
//"f83b3aa9d6317e2c756cc6bb390d7412a9dc06ecf830d00b28b620544e7c6105",
|
||||
//"bc1321ef0144be27be0df84f445f6ee481a44350920d1a1450a0918a33026d00",
|
||||
//"7be0f157e8fa2aaa256b5b396a7de64f5bce65a5ef02891020dc44c046aa5906",
|
||||
//"3664af1800ec98468a6d525153fd1b0ab8df915281b9ade05e6188a404543001",
|
||||
//"c8424e4bdbe61284d92a684f12193153f7037dd580e66693035ede5535571601",
|
||||
//"69992cbb0a157491a82dc8b8711cf23fdd72465e9dfb79c4e2cc2ff6d2fe8f0f"
|
||||
//],
|
||||
//"c1": "38387027f16b4c047be856a3fab9d8923780652bda2b701b0ee0095db9984403",
|
||||
//"D": "acd6b1face294fe2c6401d0aa885a7167c7436c660311b11300b7796623064eb"
|
||||
//}
|
||||
//],
|
||||
//"pseudoOuts": [
|
||||
//"6a8f5d7406410d3c7aea60e94c06f978ae12ada0c53d977fcbeff0a2c7599d87"
|
||||
//]
|
||||
//}
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue