aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/crypto/slow-hash.c88
-rw-r--r--src/daemon/command_server.cpp2
-rw-r--r--src/daemon/rpc_command_executor.cpp4
-rw-r--r--src/p2p/net_node.inl2
-rw-r--r--src/rpc/core_rpc_server.cpp34
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h7
-rw-r--r--src/simplewallet/simplewallet.cpp25
-rw-r--r--src/wallet/wallet2.cpp26
-rw-r--r--src/wallet/wallet2.h6
9 files changed, 157 insertions, 37 deletions
diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c
index 9ff9ff456..544083fb0 100644
--- a/src/crypto/slow-hash.c
+++ b/src/crypto/slow-hash.c
@@ -663,31 +663,71 @@ static void (*const extra_hashes[4])(const void *, size_t, char *) = {
#include "aesb.c"
-STATIC INLINE void ___mul128(uint32_t *a, uint32_t *b, uint32_t *h, uint32_t *l)
+/* The asm corresponds to this C code
+#define SHORT uint32_t
+#define LONG uint64_t
+
+void mul(const uint8_t *ca, const uint8_t *cb, uint8_t *cres) {
+ const SHORT *aa = (SHORT *)ca;
+ const SHORT *bb = (SHORT *)cb;
+ SHORT *res = (SHORT *)cres;
+ union {
+ SHORT tmp[8];
+ LONG ltmp[4];
+ } t;
+ LONG A = aa[1];
+ LONG a = aa[0];
+ LONG B = bb[1];
+ LONG b = bb[0];
+
+ // Aa * Bb = ab + aB_ + Ab_ + AB__
+ t.ltmp[0] = a * b;
+ t.ltmp[1] = a * B;
+ t.ltmp[2] = A * b;
+ t.ltmp[3] = A * B;
+
+ res[2] = t.tmp[0];
+ t.ltmp[1] += t.tmp[1];
+ t.ltmp[1] += t.tmp[4];
+ t.ltmp[3] += t.tmp[3];
+ t.ltmp[3] += t.tmp[5];
+ res[3] = t.tmp[2];
+ res[0] = t.tmp[6];
+ res[1] = t.tmp[7];
+} */
+
+/* Can work as inline, but actually runs slower. Keep it separate */
+#define mul(a, b, c) cn_mul128(a, b, c)
+void mul(const uint8_t *ca, const uint8_t *cb, uint8_t *cr)
{
- // ND: 64x64 multiplication for ARM7
- __asm__ __volatile__
- (
- // lo hi
- "umull %[r0], %[r1], %[b], %[d]\n\t" // bd [r0 = bd.lo]
- "umull %[r2], %[r3], %[b], %[c]\n\t" // bc
- "umull %[b], %[c], %[a], %[c]\n\t" // ac
- "adds %[r1], %[r1], %[r2]\n\t" // r1 = bd.hi + bc.lo
- "adcs %[r2], %[r3], %[b]\n\t" // r2 = ac.lo + bc.hi + carry
- "adc %[r3], %[c], #0\n\t" // r3 = ac.hi + carry
- "umull %[b], %[a], %[a], %[d]\n\t" // ad
- "adds %[r1], %[r1], %[b]\n\t" // r1 = bd.hi + bc.lo + ad.lo
- "adcs %[r2], %[r2], %[a]\n\t" // r2 = ac.lo + bc.hi + ad.hi + carry
- "adc %[r3], %[r3], #0\n\t" // r3 = ac.hi + carry
- : [r0]"=&r"(l[0]), [r1]"=&r"(l[1]), [r2]"=&r"(h[0]), [r3]"=&r"(h[1])
- : [a]"r"(a[1]), [b]"r"(a[0]), [c]"r"(b[1]), [d]"r"(b[0])
- : "cc"
- );
-}
-
-STATIC INLINE void mul(const uint8_t* a, const uint8_t* b, uint8_t* res)
-{
- ___mul128((uint32_t *) a, (uint32_t *) b, (uint32_t *) (res + 0), (uint32_t *) (res + 8));
+ const uint32_t *aa = (uint32_t *)ca;
+ const uint32_t *bb = (uint32_t *)cb;
+ uint32_t *r = (uint32_t *)cr;
+ uint32_t t0, t1;
+__asm__ __volatile__(
+ "umull %[t0], %[t1], %[a], %[b]\n\t"
+ "str %[t0], [%[r], #8]\n\t"
+
+ // accumulating with 0 can never overflow/carry
+ "mov %[t0], #0\n\t"
+ "umlal %[t1], %[t0], %[a], %[B]\n\t"
+
+ "mov %[a], #0\n\t"
+ "umlal %[t1], %[a], %[A], %[b]\n\t"
+ "str %[t1], [%[r], #12]\n\t"
+
+ "mov %[b], #0\n\t"
+ "umlal %[t0], %[b], %[A], %[B]\n\t"
+
+ // final add may have a carry
+ "adds %[t0], %[t0], %[a]\n\t"
+ "adc %[t1], %[b], #0\n\t"
+
+ "str %[t0], [%[r]]\n\t"
+ "str %[t1], [%[r], #4]\n\t"
+ : [t0]"=&r"(t0), [t1]"=&r"(t1)
+ : [A]"r"(aa[1]), [a]"r"(aa[0]), [B]"r"(bb[1]), [b]"r"(bb[0]), [r]"r"(r)
+ : "cc", "memory");
}
STATIC INLINE void sum_half_blocks(uint8_t* a, const uint8_t* b)
diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp
index 8f434c89a..f99b0844a 100644
--- a/src/daemon/command_server.cpp
+++ b/src/daemon/command_server.cpp
@@ -177,7 +177,7 @@ t_command_server::t_command_server(
m_command_lookup.set_handler(
"out_peers"
, std::bind(&t_command_parser_executor::out_peers, &m_parser, p::_1)
- , "Set max limit of out peers"
+ , "Set max number of out peers"
);
m_command_lookup.set_handler(
"start_save_graph"
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index 565623468..edf04bc82 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -277,7 +277,7 @@ bool t_rpc_command_executor::show_status() {
{
return true;
}
- if (!m_rpc_client->rpc_request(mreq, mres, "mining_status", fail_message.c_str()))
+ if (!m_rpc_client->rpc_request(mreq, mres, "/mining_status", fail_message.c_str()))
{
return true;
}
@@ -964,6 +964,8 @@ bool t_rpc_command_executor::out_peers(uint64_t limit)
}
}
+ std::cout << "Max number of out peers set to " << limit << std::endl;
+
return true;
}
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 3cd874f7a..47a5dc6c3 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -92,7 +92,7 @@ namespace nodetool
const command_line::arg_descriptor<bool> arg_no_igd = {"no-igd", "Disable UPnP port mapping"};
const command_line::arg_descriptor<bool> arg_offline = {"offline", "Do not listen for peers, nor connect to any"};
- const command_line::arg_descriptor<int64_t> arg_out_peers = {"out-peers", "set max limit of out peers", -1};
+ const command_line::arg_descriptor<int64_t> arg_out_peers = {"out-peers", "set max number of out peers", -1};
const command_line::arg_descriptor<int> arg_tos_flag = {"tos-flag", "set TOS flag", -1};
const command_line::arg_descriptor<int64_t> arg_limit_rate_up = {"limit-rate-up", "set limit-rate-up [kB/s]", -1};
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index e6973b0b8..0f9e2b3ab 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -304,7 +304,37 @@ namespace cryptonote
}
res.spent_status.clear();
for (size_t n = 0; n < spent_status.size(); ++n)
- res.spent_status.push_back(spent_status[n]);
+ res.spent_status.push_back(spent_status[n] ? COMMAND_RPC_IS_KEY_IMAGE_SPENT::SPENT_IN_BLOCKCHAIN : COMMAND_RPC_IS_KEY_IMAGE_SPENT::UNSPENT);
+
+ // check the pool too
+ std::vector<cryptonote::tx_info> txs;
+ std::vector<cryptonote::spent_key_image_info> ki;
+ r = m_core.get_pool_transactions_and_spent_keys_info(txs, ki);
+ if(!r)
+ {
+ res.status = "Failed";
+ return true;
+ }
+ for (std::vector<cryptonote::spent_key_image_info>::const_iterator i = ki.begin(); i != ki.end(); ++i)
+ {
+ crypto::hash hash;
+ crypto::key_image spent_key_image;
+ if (parse_hash256(i->id_hash, hash))
+ {
+ memcpy(&spent_key_image, &hash, sizeof(hash)); // a bit dodgy, should be other parse functions somewhere
+ for (size_t n = 0; n < res.spent_status.size(); ++n)
+ {
+ if (res.spent_status[n] == COMMAND_RPC_IS_KEY_IMAGE_SPENT::UNSPENT)
+ {
+ if (key_images[n] == spent_key_image)
+ {
+ res.spent_status[n] = COMMAND_RPC_IS_KEY_IMAGE_SPENT::SPENT_IN_POOL;
+ break;
+ }
+ }
+ }
+ }
+ }
res.status = CORE_RPC_STATUS_OK;
return true;
@@ -872,6 +902,7 @@ namespace cryptonote
res.height = m_core.get_current_blockchain_height();
res.target_height = m_core.get_target_blockchain_height();
res.difficulty = m_core.get_blockchain_storage().get_difficulty_for_next_block();
+ res.target = m_core.get_blockchain_storage().get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET;
res.tx_count = m_core.get_blockchain_storage().get_total_transactions() - res.height; //without coinbase
res.tx_pool_size = m_core.get_pool_transactions_count();
res.alt_blocks_count = m_core.get_blockchain_storage().get_alternative_blocks_count();
@@ -880,6 +911,7 @@ namespace cryptonote
res.incoming_connections_count = total_conn - res.outgoing_connections_count;
res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count();
res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count();
+ res.testnet = m_testnet;
res.status = CORE_RPC_STATUS_OK;
return true;
}
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 209378e5a..772d1d942 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -123,6 +123,12 @@ namespace cryptonote
//-----------------------------------------------
struct COMMAND_RPC_IS_KEY_IMAGE_SPENT
{
+ enum STATUS {
+ UNSPENT = 0,
+ SPENT_IN_BLOCKCHAIN = 1,
+ SPENT_IN_POOL = 2,
+ };
+
struct request
{
std::vector<std::string> key_images;
@@ -289,6 +295,7 @@ namespace cryptonote
KV_SERIALIZE(height)
KV_SERIALIZE(target_height)
KV_SERIALIZE(difficulty)
+ KV_SERIALIZE(target)
KV_SERIALIZE(tx_count)
KV_SERIALIZE(tx_pool_size)
KV_SERIALIZE(alt_blocks_count)
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 00bdc689d..2484cd3a5 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -37,6 +37,7 @@
#include <thread>
#include <iostream>
#include <sstream>
+#include <fstream>
#include <ctype.h>
#include <boost/lexical_cast.hpp>
#include <boost/program_options.hpp>
@@ -84,6 +85,7 @@ namespace
const command_line::arg_descriptor<std::string> arg_daemon_address = {"daemon-address", sw::tr("Use daemon instance at <host>:<port>"), ""};
const command_line::arg_descriptor<std::string> arg_daemon_host = {"daemon-host", sw::tr("Use daemon instance at host <arg> instead of localhost"), ""};
const command_line::arg_descriptor<std::string> arg_password = {"password", sw::tr("Wallet password"), "", true};
+ const command_line::arg_descriptor<std::string> arg_password_file = {"password-file", sw::tr("Wallet password file"), "", true};
const command_line::arg_descriptor<std::string> arg_electrum_seed = {"electrum-seed", sw::tr("Specify Electrum seed for wallet recovery/creation"), ""};
const command_line::arg_descriptor<bool> arg_restore_deterministic_wallet = {"restore-deterministic-wallet", sw::tr("Recover wallet using Electrum-style mnemonic seed"), false};
const command_line::arg_descriptor<bool> arg_non_deterministic = {"non-deterministic", sw::tr("Create non-deterministic view and spend keys"), false};
@@ -793,11 +795,33 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
if (m_daemon_address.empty())
m_daemon_address = std::string("http://") + m_daemon_host + ":" + std::to_string(m_daemon_port);
+ if (has_arg(vm, arg_password) && has_arg(vm, arg_password_file))
+ {
+ fail_msg_writer() << tr("can't specify more than one of --password and --password-file");
+ return false;
+ }
+
tools::password_container pwd_container;
if (command_line::has_arg(vm, arg_password))
{
pwd_container.password(command_line::get_arg(vm, arg_password));
}
+ else if (command_line::has_arg(vm, arg_password_file))
+ {
+ std::string password;
+ bool r = epee::file_io_utils::load_file_to_string(command_line::get_arg(vm, arg_password_file),
+ password);
+ if (!r)
+ {
+ fail_msg_writer() << tr("the password file specified could not be read");
+ return false;
+ }
+
+ // Remove line breaks the user might have inserted
+ password.erase(std::remove(password.begin() - 1, password.end(), '\n'), password.end());
+ password.erase(std::remove(password.end() - 1, password.end(), '\r'), password.end());
+ pwd_container.password(password.c_str());
+ }
else
{
bool r = pwd_container.read_password();
@@ -2418,6 +2442,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_generate_new_wallet);
command_line::add_arg(desc_params, arg_generate_from_view_key);
command_line::add_arg(desc_params, arg_password);
+ command_line::add_arg(desc_params, arg_password_file);
command_line::add_arg(desc_params, arg_daemon_address);
command_line::add_arg(desc_params, arg_daemon_host);
command_line::add_arg(desc_params, arg_daemon_port);
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index bceea367f..3edbaeca2 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -1419,15 +1419,15 @@ void wallet2::rescan_spent()
for (size_t i = 0; i < m_transfers.size(); ++i)
{
transfer_details& td = m_transfers[i];
- if (td.m_spent != daemon_resp.spent_status[i])
+ if (td.m_spent != (daemon_resp.spent_status[i] != COMMAND_RPC_IS_KEY_IMAGE_SPENT::UNSPENT))
{
if (td.m_spent)
{
- LOG_PRINT_L1("Marking output " << i << " as unspent, it was marked as spent");
+ LOG_PRINT_L0("Marking output " << i << "(" << td.m_key_image << ") as unspent, it was marked as spent");
}
else
{
- LOG_PRINT_L1("Marking output " << i << " as spent, it was marked as unspent");
+ LOG_PRINT_L0("Marking output " << i << "(" << td.m_key_image << ") as spent, it was marked as unspent");
}
td.m_spent = daemon_resp.spent_status[i];
}
@@ -1880,6 +1880,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
// throw if attempting a transaction with no destinations
THROW_WALLET_EXCEPTION_IF(dsts.empty(), error::zero_destination);
+ uint64_t upper_transaction_size_limit = get_upper_tranaction_size_limit();
uint64_t needed_money = fee;
LOG_PRINT_L2("transfer: starting with fee " << print_money (needed_money));
@@ -2005,7 +2006,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
crypto::secret_key tx_key;
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key);
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
- THROW_WALLET_EXCEPTION_IF(m_upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, m_upper_transaction_size_limit);
+ THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
std::string key_images;
bool all_are_txin_to_key = std::all_of(tx.vin.begin(), tx.vin.end(), [&](const txin_v& s_e) -> bool
@@ -2066,6 +2067,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
std::vector<TX> txes;
bool adding_fee; // true if new outputs go towards fee, rather than destinations
uint64_t needed_fee, available_for_fee = 0;
+ uint64_t upper_transaction_size_limit = get_upper_tranaction_size_limit();
// throw if attempting a transaction with no destinations
THROW_WALLET_EXCEPTION_IF(dsts.empty(), error::zero_destination);
@@ -2158,7 +2160,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
// here, check if we need to sent tx and start a new one
LOG_PRINT_L2("Considering whether to create a tx now, " << tx.selected_transfers.size() << " inputs, tx limit "
- << m_upper_transaction_size_limit);
+ << upper_transaction_size_limit);
bool try_tx;
if (adding_fee)
{
@@ -2167,7 +2169,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
}
else
{
- try_tx = dsts.empty() || (tx.selected_transfers.size() * (fake_outs_count+1) * APPROXIMATE_INPUT_BYTES >= TX_SIZE_TARGET(m_upper_transaction_size_limit));
+ try_tx = dsts.empty() || (tx.selected_transfers.size() * (fake_outs_count+1) * APPROXIMATE_INPUT_BYTES >= TX_SIZE_TARGET(upper_transaction_size_limit));
}
if (try_tx) {
@@ -2290,6 +2292,8 @@ void wallet2::transfer_dust(size_t num_outputs, uint64_t unlock_time, uint64_t n
{
using namespace cryptonote;
+ uint64_t upper_transaction_size_limit = get_upper_tranaction_size_limit();
+
// select all dust inputs for transaction
// throw if there are none
uint64_t money = 0;
@@ -2354,7 +2358,7 @@ void wallet2::transfer_dust(size_t num_outputs, uint64_t unlock_time, uint64_t n
crypto::secret_key tx_key;
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key);
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
- THROW_WALLET_EXCEPTION_IF(m_upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, m_upper_transaction_size_limit);
+ THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
std::string key_images;
bool all_are_txin_to_key = std::all_of(tx.vin.begin(), tx.vin.end(), [&](const txin_v& s_e) -> bool
@@ -2409,6 +2413,14 @@ bool wallet2::use_fork_rules(uint8_t version)
return close_enough;
}
//----------------------------------------------------------------------------------------------------
+uint64_t wallet2::get_upper_tranaction_size_limit()
+{
+ if (m_upper_transaction_size_limit > 0)
+ return m_upper_transaction_size_limit;
+ uint64_t full_reward_zone = use_fork_rules(2) ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE : CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1;
+ return ((full_reward_zone * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
+}
+//----------------------------------------------------------------------------------------------------
std::vector<wallet2::pending_tx> wallet2::create_dust_sweep_transactions()
{
// From hard fork 1, we don't consider small amounts to be dust anymore
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 256154b4a..9912226c6 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -214,7 +214,7 @@ namespace tools
// free block size. TODO: fix this so that it actually takes
// into account the current median block size rather than
// the minimum block size.
- void init(const std::string& daemon_address = "http://localhost:8080", uint64_t upper_transaction_size_limit = ((CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE);
+ void init(const std::string& daemon_address = "http://localhost:8080", uint64_t upper_transaction_size_limit = 0);
bool deinit();
void stop() { m_run.store(false, std::memory_order_relaxed); }
@@ -374,6 +374,7 @@ namespace tools
void check_acc_out(const cryptonote::account_keys &acc, const cryptonote::tx_out &o, const crypto::public_key &tx_pub_key, size_t i, uint64_t &money_transfered, bool &error) const;
void parse_block_round(const cryptonote::blobdata &blob, cryptonote::block &bl, crypto::hash &bl_id, bool &error) const;
bool use_fork_rules(uint8_t version);
+ uint64_t get_upper_tranaction_size_limit();
cryptonote::account_base m_account;
std::string m_daemon_address;
@@ -543,6 +544,7 @@ namespace tools
// throw if attempting a transaction with no destinations
THROW_WALLET_EXCEPTION_IF(dsts.empty(), error::zero_destination);
+ uint64_t upper_transaction_size_limit = get_upper_tranaction_size_limit();
uint64_t needed_money = fee;
// calculate total amount being sent to all destinations
@@ -664,7 +666,7 @@ namespace tools
crypto::secret_key tx_key;
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key);
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
- THROW_WALLET_EXCEPTION_IF(m_upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, m_upper_transaction_size_limit);
+ THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
std::string key_images;
bool all_are_txin_to_key = std::all_of(tx.vin.begin(), tx.vin.end(), [&](const txin_v& s_e) -> bool