aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/daemon/rpc_command_executor.cpp2
-rw-r--r--src/rpc/core_rpc_server.cpp14
-rw-r--r--src/rpc/core_rpc_server.h3
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h14
-rw-r--r--src/wallet/wallet_rpc_server.cpp6
-rwxr-xr-xtests/functional_tests/transfer.py50
-rw-r--r--utils/python-rpc/framework/wallet.py21
7 files changed, 96 insertions, 14 deletions
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index 47c33b8f9..186296dc9 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -2205,7 +2205,7 @@ bool t_rpc_command_executor::prune_blockchain()
}
}
- tools::success_msg_writer() << "Blockchain pruned: seed " << epee::string_tools::to_string_hex(res.pruning_seed);
+ tools::success_msg_writer() << "Blockchain pruned";
return true;
}
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 6df0772c3..ffd2a0113 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -575,7 +575,7 @@ namespace cryptonote
// try the pool for any missing txes
size_t found_in_pool = 0;
std::unordered_set<crypto::hash> pool_tx_hashes;
- std::unordered_map<crypto::hash, bool> double_spend_seen;
+ std::unordered_map<crypto::hash, tx_info> per_tx_pool_tx_info;
if (!missed_txs.empty())
{
std::vector<tx_info> pool_tx_info;
@@ -630,7 +630,7 @@ namespace cryptonote
{
if (ti.id_hash == hash_string)
{
- double_spend_seen.insert(std::make_pair(h, ti.double_spend_seen));
+ per_tx_pool_tx_info.insert(std::make_pair(h, ti));
break;
}
}
@@ -716,14 +716,17 @@ namespace cryptonote
if (e.in_pool)
{
e.block_height = e.block_timestamp = std::numeric_limits<uint64_t>::max();
- if (double_spend_seen.find(tx_hash) != double_spend_seen.end())
+ auto it = per_tx_pool_tx_info.find(tx_hash);
+ if (it != per_tx_pool_tx_info.end())
{
- e.double_spend_seen = double_spend_seen[tx_hash];
+ e.double_spend_seen = it->second.double_spend_seen;
+ e.relayed = it->second.relayed;
}
else
{
- MERROR("Failed to determine double spend status for " << tx_hash);
+ MERROR("Failed to determine pool info for " << tx_hash);
e.double_spend_seen = false;
+ e.relayed = false;
}
}
else
@@ -731,6 +734,7 @@ namespace cryptonote
e.block_height = m_core.get_blockchain_storage().get_db().get_tx_block_height(tx_hash);
e.block_timestamp = m_core.get_blockchain_storage().get_db().get_block_timestamp(e.block_height);
e.double_spend_seen = false;
+ e.relayed = false;
}
// fill up old style responses too, in case an old wallet asks
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index a42ca2494..e4683bbe2 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -40,6 +40,9 @@
#include "p2p/net_node.h"
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
+#undef MONERO_DEFAULT_LOG_CATEGORY
+#define MONERO_DEFAULT_LOG_CATEGORY "daemon.rpc"
+
// yes, epee doesn't properly use its full namespace when calling its
// functions from macros. *sigh*
using namespace epee;
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index a1e2fdf8d..8342e88b1 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -364,6 +364,7 @@ namespace cryptonote
uint64_t block_height;
uint64_t block_timestamp;
std::vector<uint64_t> output_indices;
+ bool relayed;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash)
@@ -374,9 +375,16 @@ namespace cryptonote
KV_SERIALIZE(as_json)
KV_SERIALIZE(in_pool)
KV_SERIALIZE(double_spend_seen)
- KV_SERIALIZE(block_height)
- KV_SERIALIZE(block_timestamp)
- KV_SERIALIZE(output_indices)
+ if (!this_ref.in_pool)
+ {
+ KV_SERIALIZE(block_height)
+ KV_SERIALIZE(block_timestamp)
+ KV_SERIALIZE(output_indices)
+ }
+ else
+ {
+ KV_SERIALIZE(relayed)
+ }
END_KV_SERIALIZE_MAP()
};
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 24981980c..2039c6742 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -1842,11 +1842,7 @@ namespace tools
{
if (req.account_index != td.m_subaddr_index.major || (!req.subaddr_indices.empty() && req.subaddr_indices.count(td.m_subaddr_index.minor) == 0))
continue;
- if (!transfers_found)
- {
- transfers_found = true;
- }
- auto txBlob = t_serializable_object_to_blob(td.m_tx);
+ transfers_found = true;
wallet_rpc::transfer_details rpc_transfers;
rpc_transfers.amount = td.amount();
rpc_transfers.spent = td.m_spent;
diff --git a/tests/functional_tests/transfer.py b/tests/functional_tests/transfer.py
index 050277c51..bc2f5472b 100755
--- a/tests/functional_tests/transfer.py
+++ b/tests/functional_tests/transfer.py
@@ -29,6 +29,7 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import time
+import json
"""Test simple transfers
"""
@@ -43,6 +44,7 @@ class TransferTest():
self.transfer()
self.check_get_bulk_payments()
self.check_double_spend_detection()
+ self.sweep_single()
def create(self):
print 'Creating wallets'
@@ -569,6 +571,54 @@ class TransferTest():
assert tx.in_pool
assert tx.double_spend_seen
+ def sweep_single(self):
+ daemon = Daemon()
+
+ print("Sending single output")
+
+ daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1)
+ self.wallet[0].refresh()
+ res = self.wallet[0].incoming_transfers(transfer_type = 'available')
+ for t in res.transfers:
+ assert not t.spent
+ assert len(res.transfers) > 8 # we mined a lot
+ index = 8
+ assert not res.transfers[index].spent
+ assert res.transfers[index].amount > 0
+ ki = res.transfers[index].key_image
+ amount = res.transfers[index].amount
+ daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 10) # ensure unlocked
+ self.wallet[0].refresh()
+ res = self.wallet[0].get_balance()
+ balance = res.balance
+ res = self.wallet[0].incoming_transfers(transfer_type = 'all')
+ res = self.wallet[0].sweep_single('44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', key_image = ki)
+ assert len(res.tx_hash) == 64
+ tx_hash = res.tx_hash
+ daemon.generateblocks('44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 1)
+ self.wallet[0].refresh()
+ res = self.wallet[0].get_balance()
+ new_balance = res.balance
+ res = daemon.get_transactions([tx_hash], decode_as_json = True)
+ assert len(res.txs) == 1
+ tx = res.txs[0]
+ assert tx.tx_hash == tx_hash
+ assert not tx.in_pool
+ assert len(tx.as_json) > 0
+ try:
+ j = json.loads(tx.as_json)
+ except:
+ j = None
+ assert j
+ assert new_balance == balance - amount
+ assert len(j['vin']) == 1
+ assert j['vin'][0]['key']['k_image'] == ki
+ self.wallet[0].refresh()
+ res = self.wallet[0].incoming_transfers(transfer_type = 'available')
+ assert len([t for t in res.transfers if t.key_image == ki]) == 0
+ res = self.wallet[0].incoming_transfers(transfer_type = 'unavailable')
+ assert len([t for t in res.transfers if t.key_image == ki]) == 1
+
if __name__ == '__main__':
TransferTest().run_test()
diff --git a/utils/python-rpc/framework/wallet.py b/utils/python-rpc/framework/wallet.py
index a55750e3a..695325a86 100644
--- a/utils/python-rpc/framework/wallet.py
+++ b/utils/python-rpc/framework/wallet.py
@@ -184,6 +184,27 @@ class Wallet(object):
}
return self.rpc.send_json_rpc_request(sweep_all)
+ def sweep_single(self, address = '', priority = 0, ring_size = 0, outputs = 1, unlock_time = 0, payment_id = '', get_tx_keys = False, key_image = "", do_not_relay = False, get_tx_hex = False, get_tx_metadata = False):
+ sweep_single = {
+ 'method': 'sweep_single',
+ 'params' : {
+ 'address' : address,
+ 'priority' : priority,
+ 'ring_size' : ring_size,
+ 'outputs' : outputs,
+ 'unlock_time' : unlock_time,
+ 'payment_id' : payment_id,
+ 'get_tx_keys' : get_tx_keys,
+ 'key_image' : key_image,
+ 'do_not_relay' : do_not_relay,
+ 'get_tx_hex' : get_tx_hex,
+ 'get_tx_metadata' : get_tx_metadata,
+ },
+ 'jsonrpc': '2.0',
+ 'id': '0'
+ }
+ return self.rpc.send_json_rpc_request(sweep_single)
+
def get_address(self, account_index = 0, subaddresses = []):
get_address = {
'method': 'get_address',