Transaction history and 'reset' command for simplewallet
This commit is contained in:
parent
c3b1a00085
commit
9df3a81801
17 changed files with 376 additions and 98 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
Release notes 1.0.2
|
||||||
|
|
||||||
|
- Transaction history for simplewallet
|
||||||
|
- Reset command for simplewallet
|
||||||
|
- Various simplewallet improvements
|
||||||
|
|
||||||
Release notes 1.0.1
|
Release notes 1.0.1
|
||||||
|
|
||||||
- Fix transfers in simplewallet
|
- Fix transfers in simplewallet
|
||||||
|
|
|
@ -63,6 +63,7 @@ const uint64_t CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS = DIFFICULTY_TARGET
|
||||||
const uint64_t CRYPTONOTE_MEMPOOL_TX_LIVETIME = 60 * 60 * 24; //seconds, one day
|
const uint64_t CRYPTONOTE_MEMPOOL_TX_LIVETIME = 60 * 60 * 24; //seconds, one day
|
||||||
const uint64_t CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME = 60 * 60 * 24 * 7; //seconds, one week
|
const uint64_t CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME = 60 * 60 * 24 * 7; //seconds, one week
|
||||||
|
|
||||||
|
const uint64_t UPGRADE_HEIGHT = 546602;
|
||||||
const unsigned UPGRADE_VOTING_THRESHOLD = 90; // percent
|
const unsigned UPGRADE_VOTING_THRESHOLD = 90; // percent
|
||||||
const size_t UPGRADE_VOTING_WINDOW = EXPECTED_NUMBER_OF_BLOCKS_PER_DAY; // blocks
|
const size_t UPGRADE_VOTING_WINDOW = EXPECTED_NUMBER_OF_BLOCKS_PER_DAY; // blocks
|
||||||
const size_t UPGRADE_WINDOW = EXPECTED_NUMBER_OF_BLOCKS_PER_DAY; // blocks
|
const size_t UPGRADE_WINDOW = EXPECTED_NUMBER_OF_BLOCKS_PER_DAY; // blocks
|
||||||
|
@ -104,7 +105,7 @@ const uint32_t P2P_DEFAULT_CONNECTION_TIMEOUT = 5000; //
|
||||||
const uint32_t P2P_DEFAULT_PING_CONNECTION_TIMEOUT = 2000; // 2 seconds
|
const uint32_t P2P_DEFAULT_PING_CONNECTION_TIMEOUT = 2000; // 2 seconds
|
||||||
const uint64_t P2P_DEFAULT_INVOKE_TIMEOUT = 60 * 2 * 1000; // 2 minutes
|
const uint64_t P2P_DEFAULT_INVOKE_TIMEOUT = 60 * 2 * 1000; // 2 minutes
|
||||||
const size_t P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT = 5000; // 5 seconds
|
const size_t P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT = 5000; // 5 seconds
|
||||||
const char P2P_STAT_TRUSTED_PUB_KEY[] = "8f80f9a5a434a9f1510d13336228debfee9c918ce505efe225d8c94d045fa115";
|
const char P2P_STAT_TRUSTED_PUB_KEY[] = "93467628927eaa0b13a4e52e61864a75aa475e67f6b5748eb3fc1d2fe468aed4";
|
||||||
const size_t P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT = 70;
|
const size_t P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT = 70;
|
||||||
|
|
||||||
const unsigned THREAD_STACK_SIZE = 5 * 1024 * 1024;
|
const unsigned THREAD_STACK_SIZE = 5 * 1024 * 1024;
|
||||||
|
@ -143,7 +144,8 @@ const CheckpointData CHECKPOINTS[] = {
|
||||||
{480200, "363544ac9920c778b815c2fdbcbca70a0d79b21f662913a42da9b49e859f0e5b"},
|
{480200, "363544ac9920c778b815c2fdbcbca70a0d79b21f662913a42da9b49e859f0e5b"},
|
||||||
{484500, "5cdf2101a0a62a0ab2a1ca0c15a6212b21f6dbdc42a0b7c0bcf65ca40b7a14fb"},
|
{484500, "5cdf2101a0a62a0ab2a1ca0c15a6212b21f6dbdc42a0b7c0bcf65ca40b7a14fb"},
|
||||||
{506000, "3d54c1132f503d98d3f0d78bb46a4503c1a19447cb348361a2232e241cb45a3c"},
|
{506000, "3d54c1132f503d98d3f0d78bb46a4503c1a19447cb348361a2232e241cb45a3c"},
|
||||||
{544000, "f69dc61b6a63217f32fa64d5d0f9bd920873f57dfd79ebe1d7d6fb1345b56fe0"}
|
{544000, "f69dc61b6a63217f32fa64d5d0f9bd920873f57dfd79ebe1d7d6fb1345b56fe0"},
|
||||||
|
{553300, "f7a5076b887ce5f4bb95b2729c0edb6f077a463f04f1bffe7f5cb0b16bb8aa5f"}
|
||||||
};
|
};
|
||||||
} // cryptonote
|
} // cryptonote
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace cryptonote {
|
||||||
CHECK_AND_ASSERT_MES(r, false, "Failed to get genesis block hash");
|
CHECK_AND_ASSERT_MES(r, false, "Failed to get genesis block hash");
|
||||||
|
|
||||||
if (isTestnet()) {
|
if (isTestnet()) {
|
||||||
|
m_upgradeHeight = 0;
|
||||||
m_blocksFileName = "testnet_" + m_blocksFileName;
|
m_blocksFileName = "testnet_" + m_blocksFileName;
|
||||||
m_blocksCacheFileName = "testnet_" + m_blocksCacheFileName;
|
m_blocksCacheFileName = "testnet_" + m_blocksCacheFileName;
|
||||||
m_blockIndexesFileName = "testnet_" + m_blockIndexesFileName;
|
m_blockIndexesFileName = "testnet_" + m_blockIndexesFileName;
|
||||||
|
@ -380,7 +381,7 @@ namespace cryptonote {
|
||||||
mempoolTxLiveTime(parameters::CRYPTONOTE_MEMPOOL_TX_LIVETIME);
|
mempoolTxLiveTime(parameters::CRYPTONOTE_MEMPOOL_TX_LIVETIME);
|
||||||
mempoolTxFromAltBlockLiveTime(parameters::CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME);
|
mempoolTxFromAltBlockLiveTime(parameters::CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME);
|
||||||
|
|
||||||
upgradeHeight(UpgradeDetectorBase::UNDEF_HEIGHT);
|
upgradeHeight(parameters::UPGRADE_HEIGHT);
|
||||||
upgradeVotingThreshold(parameters::UPGRADE_VOTING_THRESHOLD);
|
upgradeVotingThreshold(parameters::UPGRADE_VOTING_THRESHOLD);
|
||||||
upgradeVotingWindow(parameters::UPGRADE_VOTING_WINDOW);
|
upgradeVotingWindow(parameters::UPGRADE_VOTING_WINDOW);
|
||||||
upgradeWindow(parameters::UPGRADE_WINDOW);
|
upgradeWindow(parameters::UPGRADE_WINDOW);
|
||||||
|
|
|
@ -231,8 +231,9 @@ namespace cryptonote
|
||||||
if (version < CURRENT_BLOCKCACHE_STORAGE_ARCHIVE_VER)
|
if (version < CURRENT_BLOCKCACHE_STORAGE_ARCHIVE_VER)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
std::string operation;
|
||||||
if (Archive::is_loading::value) {
|
if (Archive::is_loading::value) {
|
||||||
|
operation = "- loading ";
|
||||||
crypto::hash blockHash;
|
crypto::hash blockHash;
|
||||||
ar & blockHash;
|
ar & blockHash;
|
||||||
|
|
||||||
|
@ -241,13 +242,23 @@ namespace cryptonote
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
operation = "- saving ";
|
||||||
ar & m_lastBlockHash;
|
ar & m_lastBlockHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_PRINT_L0(operation << "block index...");
|
||||||
ar & m_bs.m_blockIndex;
|
ar & m_bs.m_blockIndex;
|
||||||
|
|
||||||
|
LOG_PRINT_L0(operation << "transaction map...");
|
||||||
ar & m_bs.m_transactionMap;
|
ar & m_bs.m_transactionMap;
|
||||||
|
|
||||||
|
LOG_PRINT_L0(operation << "spend keys...");
|
||||||
ar & m_bs.m_spent_keys;
|
ar & m_bs.m_spent_keys;
|
||||||
|
|
||||||
|
LOG_PRINT_L0(operation << "outputs...");
|
||||||
ar & m_bs.m_outputs;
|
ar & m_bs.m_outputs;
|
||||||
|
|
||||||
|
LOG_PRINT_L0(operation << "multi-signature outputs...");
|
||||||
ar & m_bs.m_multisignatureOutputs;
|
ar & m_bs.m_multisignatureOutputs;
|
||||||
|
|
||||||
m_loaded = true;
|
m_loaded = true;
|
||||||
|
@ -377,6 +388,9 @@ bool blockchain_storage::init(const std::string& config_folder, bool load_existi
|
||||||
m_outputs.clear();
|
m_outputs.clear();
|
||||||
m_multisignatureOutputs.clear();
|
m_multisignatureOutputs.clear();
|
||||||
for (uint32_t b = 0; b < m_blocks.size(); ++b) {
|
for (uint32_t b = 0; b < m_blocks.size(); ++b) {
|
||||||
|
if (b % 1000 == 0) {
|
||||||
|
std::cout << "Height " << b << " of " << m_blocks.size() << '\r';
|
||||||
|
}
|
||||||
const BlockEntry& block = m_blocks[b];
|
const BlockEntry& block = m_blocks[b];
|
||||||
crypto::hash blockHash = get_block_hash(block.bl);
|
crypto::hash blockHash = get_block_hash(block.bl);
|
||||||
m_blockIndex.push(blockHash);
|
m_blockIndex.push(blockHash);
|
||||||
|
@ -435,6 +449,7 @@ bool blockchain_storage::init(const std::string& config_folder, bool load_existi
|
||||||
bool blockchain_storage::storeCache() {
|
bool blockchain_storage::storeCache() {
|
||||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||||
|
|
||||||
|
LOG_PRINT_L0("Saving blockchain...");
|
||||||
BlockCacheSerializer ser(*this, get_tail_id());
|
BlockCacheSerializer ser(*this, get_tail_id());
|
||||||
if (!tools::serialize_obj_to_file(ser, appendPath(m_config_folder, m_currency.blocksCacheFileName()))) {
|
if (!tools::serialize_obj_to_file(ser, appendPath(m_config_folder, m_currency.blocksCacheFileName()))) {
|
||||||
LOG_ERROR("Failed to save blockchain cache");
|
LOG_ERROR("Failed to save blockchain cache");
|
||||||
|
@ -900,9 +915,9 @@ bool blockchain_storage::handle_alternative_block(const Block& b, const crypto::
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_checkpoints.is_alternative_block_allowed(get_current_blockchain_height(), block_height)) {
|
if (!m_checkpoints.is_alternative_block_allowed(get_current_blockchain_height(), block_height)) {
|
||||||
LOG_PRINT_RED_L0("Block with id: " << id
|
LOG_PRINT_L2("Block with id: " << id << std::endl <<
|
||||||
<< ENDL << " can't be accepted for alternative chain, block height: " << block_height
|
" can't be accepted for alternative chain, block height: " << block_height << std::endl <<
|
||||||
<< ENDL << " blockchain height: " << get_current_blockchain_height());
|
" blockchain height: " << get_current_blockchain_height());
|
||||||
bvc.m_verifivation_failed = true;
|
bvc.m_verifivation_failed = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1525,7 +1540,7 @@ bool blockchain_storage::checkBlockVersion(const Block& b, const crypto::hash& b
|
||||||
uint64_t height = get_block_height(b);
|
uint64_t height = get_block_height(b);
|
||||||
const uint8_t expectedBlockVersion = get_block_major_version_for_height(height);
|
const uint8_t expectedBlockVersion = get_block_major_version_for_height(height);
|
||||||
if (b.majorVersion != expectedBlockVersion) {
|
if (b.majorVersion != expectedBlockVersion) {
|
||||||
LOG_PRINT_L0("Block " << blockHash << " has wrong major version: " << static_cast<int>(b.majorVersion) <<
|
LOG_PRINT_L2("Block " << blockHash << " has wrong major version: " << static_cast<int>(b.majorVersion) <<
|
||||||
", at height " << height << " expected version is " << static_cast<int>(expectedBlockVersion));
|
", at height " << height << " expected version is " << static_cast<int>(expectedBlockVersion));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,7 +257,7 @@ namespace cryptonote
|
||||||
|
|
||||||
if(!keeped_by_block && get_object_blobsize(tx) >= m_blockchain_storage.get_current_comulative_blocksize_limit() - m_currency.minerTxBlobReservedSize())
|
if(!keeped_by_block && get_object_blobsize(tx) >= m_blockchain_storage.get_current_comulative_blocksize_limit() - m_currency.minerTxBlobReservedSize())
|
||||||
{
|
{
|
||||||
LOG_PRINT_RED_L0("tx have to big size " << get_object_blobsize(tx) << ", expected not bigger than " <<
|
LOG_PRINT_RED_L0("transaction is too big " << get_object_blobsize(tx) << ", maximum allowed size is " <<
|
||||||
(m_blockchain_storage.get_current_comulative_blocksize_limit() - m_currency.minerTxBlobReservedSize()));
|
(m_blockchain_storage.get_current_comulative_blocksize_limit() - m_currency.minerTxBlobReservedSize()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,9 +123,9 @@ namespace cryptonote
|
||||||
|
|
||||||
int64_t diff = static_cast<int64_t>(hshd.current_height) - static_cast<int64_t>(m_core.get_current_blockchain_height());
|
int64_t diff = static_cast<int64_t>(hshd.current_height) - static_cast<int64_t>(m_core.get_current_blockchain_height());
|
||||||
LOG_PRINT_CCONTEXT_YELLOW("Sync data returned unknown top block: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height
|
LOG_PRINT_CCONTEXT_YELLOW("Sync data returned unknown top block: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height
|
||||||
<< " [" << std::abs(diff) << " blocks (" << diff / (24 * 60 * 60 / m_core.currency().difficultyTarget()) << " days) "
|
<< " [" << std::abs(diff) << " blocks (" << std::abs(diff) / (24 * 60 * 60 / m_core.currency().difficultyTarget()) << " days) "
|
||||||
<< (0 <= diff ? std::string("behind") : std::string("ahead"))
|
<< (diff >= 0 ? std::string("behind") : std::string("ahead")) << "] " << std::endl <<
|
||||||
<< "] " << ENDL << "SYNCHRONIZATION started", (is_inital ? LOG_LEVEL_0:LOG_LEVEL_1));
|
"SYNCHRONIZATION started", (diff >= 0 ? (is_inital ? LOG_LEVEL_0 : LOG_LEVEL_1) : LOG_LEVEL_2));
|
||||||
LOG_PRINT_L1("Remote top block height: " << hshd.current_height << ", id: " << hshd.top_id);
|
LOG_PRINT_L1("Remote top block height: " << hshd.current_height << ", id: " << hshd.top_id);
|
||||||
context.m_state = cryptonote_connection_context::state_synchronizing;
|
context.m_state = cryptonote_connection_context::state_synchronizing;
|
||||||
context.m_remote_blockchain_height = hshd.current_height;
|
context.m_remote_blockchain_height = hshd.current_height;
|
||||||
|
@ -173,7 +173,7 @@ namespace cryptonote
|
||||||
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
||||||
m_core.handle_incoming_block_blob(arg.b.block, bvc, true, false);
|
m_core.handle_incoming_block_blob(arg.b.block, bvc, true, false);
|
||||||
if (bvc.m_verifivation_failed) {
|
if (bvc.m_verifivation_failed) {
|
||||||
LOG_PRINT_CCONTEXT_L0("Block verification failed, dropping connection");
|
LOG_PRINT_CCONTEXT_L1("Block verification failed, dropping connection");
|
||||||
m_p2p->drop_connection(context);
|
m_p2p->drop_connection(context);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -332,7 +332,7 @@ namespace cryptonote
|
||||||
m_core.handle_incoming_block_blob(block_entry.block, bvc, false, false);
|
m_core.handle_incoming_block_blob(block_entry.block, bvc, false, false);
|
||||||
|
|
||||||
if (bvc.m_verifivation_failed) {
|
if (bvc.m_verifivation_failed) {
|
||||||
LOG_PRINT_CCONTEXT_L0("Block verification failed, dropping connection");
|
LOG_PRINT_CCONTEXT_L1("Block verification failed, dropping connection");
|
||||||
m_p2p->drop_connection(context);
|
m_p2p->drop_connection(context);
|
||||||
return 1;
|
return 1;
|
||||||
} else if (bvc.m_marked_as_orphaned) {
|
} else if (bvc.m_marked_as_orphaned) {
|
||||||
|
|
|
@ -230,7 +230,7 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!r) {
|
if (!r) {
|
||||||
fail_msg_writer() << "payment id has invalid format: \"" << value << "\", expected 64-character string";
|
fail_msg_writer() << "payment ID has invalid format: \"" << value << "\", expected 64-character string";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (arg == "-f") {
|
} else if (arg == "-f") {
|
||||||
|
@ -249,7 +249,13 @@ namespace
|
||||||
cryptonote::tx_destination_entry de;
|
cryptonote::tx_destination_entry de;
|
||||||
|
|
||||||
if (!m_currency.parseAccountAddressString(arg, de.addr)) {
|
if (!m_currency.parseAccountAddressString(arg, de.addr)) {
|
||||||
fail_msg_writer() << "wrong address: " << arg;
|
crypto::hash paymentId;
|
||||||
|
if (tools::wallet2::parse_payment_id(arg, paymentId)) {
|
||||||
|
fail_msg_writer() << "Invalid payment ID usage. Please, use -p <payment_id>. See help for details.";
|
||||||
|
} else {
|
||||||
|
fail_msg_writer() << "Wrong address: " << arg;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,6 +313,7 @@ simple_wallet::simple_wallet(const cryptonote::Currency& currency)
|
||||||
m_cmd_binder.set_handler("refresh", boost::bind(&simple_wallet::refresh, this, _1), "Resynchronize transactions and balance");
|
m_cmd_binder.set_handler("refresh", boost::bind(&simple_wallet::refresh, this, _1), "Resynchronize transactions and balance");
|
||||||
m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, _1), "Show current wallet balance");
|
m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, _1), "Show current wallet balance");
|
||||||
m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, _1), "incoming_transfers [available|unavailable] - Show incoming transfers - all of them or filter them by availability");
|
m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, _1), "incoming_transfers [available|unavailable] - Show incoming transfers - all of them or filter them by availability");
|
||||||
|
m_cmd_binder.set_handler("list_transfers", boost::bind(&simple_wallet::listTransfers, this, _1), "Show all known transfers");
|
||||||
m_cmd_binder.set_handler("payments", boost::bind(&simple_wallet::show_payments, this, _1), "payments <payment_id_1> [<payment_id_2> ... <payment_id_N>] - Show payments <payment_id_1>, ... <payment_id_N>");
|
m_cmd_binder.set_handler("payments", boost::bind(&simple_wallet::show_payments, this, _1), "payments <payment_id_1> [<payment_id_2> ... <payment_id_N>] - Show payments <payment_id_1>, ... <payment_id_N>");
|
||||||
m_cmd_binder.set_handler("bc_height", boost::bind(&simple_wallet::show_blockchain_height, this, _1), "Show blockchain height");
|
m_cmd_binder.set_handler("bc_height", boost::bind(&simple_wallet::show_blockchain_height, this, _1), "Show blockchain height");
|
||||||
m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer, this, _1),
|
m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer, this, _1),
|
||||||
|
@ -316,6 +323,7 @@ simple_wallet::simple_wallet(const cryptonote::Currency& currency)
|
||||||
m_cmd_binder.set_handler("set_log", boost::bind(&simple_wallet::set_log, this, _1), "set_log <level> - Change current log detalization level, <level> is a number 0-4");
|
m_cmd_binder.set_handler("set_log", boost::bind(&simple_wallet::set_log, this, _1), "set_log <level> - Change current log detalization level, <level> is a number 0-4");
|
||||||
m_cmd_binder.set_handler("address", boost::bind(&simple_wallet::print_address, this, _1), "Show current wallet public address");
|
m_cmd_binder.set_handler("address", boost::bind(&simple_wallet::print_address, this, _1), "Show current wallet public address");
|
||||||
m_cmd_binder.set_handler("save", boost::bind(&simple_wallet::save, this, _1), "Save wallet synchronized data");
|
m_cmd_binder.set_handler("save", boost::bind(&simple_wallet::save, this, _1), "Save wallet synchronized data");
|
||||||
|
m_cmd_binder.set_handler("reset", boost::bind(&simple_wallet::reset, this, _1), "Discard cache data and start synchronizing from the start");
|
||||||
m_cmd_binder.set_handler("help", boost::bind(&simple_wallet::help, this, _1), "Show this help");
|
m_cmd_binder.set_handler("help", boost::bind(&simple_wallet::help, this, _1), "Show this help");
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
@ -560,7 +568,14 @@ bool simple_wallet::save(const std::vector<std::string> &args)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
|
||||||
|
bool simple_wallet::reset(const std::vector<std::string> &args) {
|
||||||
|
m_wallet->reset();
|
||||||
|
success_msg_writer(true) << "Reset is complete successfully";
|
||||||
|
refresh();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool simple_wallet::start_mining(const std::vector<std::string>& args)
|
bool simple_wallet::start_mining(const std::vector<std::string>& args)
|
||||||
{
|
{
|
||||||
if (!try_connect_to_daemon())
|
if (!try_connect_to_daemon())
|
||||||
|
@ -652,7 +667,7 @@ void simple_wallet::on_skip_transaction(uint64_t height, const cryptonote::Trans
|
||||||
m_refresh_progress_reporter.update(height, true);
|
m_refresh_progress_reporter.update(height, true);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
bool simple_wallet::refresh(const std::vector<std::string>& args)
|
bool simple_wallet::refresh(const std::vector<std::string>& args/* = std::vector<std::string>()*/)
|
||||||
{
|
{
|
||||||
if (!try_connect_to_daemon())
|
if (!try_connect_to_daemon())
|
||||||
return true;
|
return true;
|
||||||
|
@ -776,12 +791,35 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
|
||||||
|
bool simple_wallet::listTransfers(const std::vector<std::string>& args) {
|
||||||
|
const std::vector<tools::wallet2::Transfer>& transfers = m_wallet->getTransfers();
|
||||||
|
for (const tools::wallet2::Transfer& transfer : transfers) {
|
||||||
|
std::string address = "UNKNOWN";
|
||||||
|
if (transfer.hasAddress) {
|
||||||
|
address = getAccountAddressAsStr(m_currency.publicAddressBase58Prefix(), transfer.address);
|
||||||
|
}
|
||||||
|
|
||||||
|
message_writer(transfer.output ? epee::log_space::console_color_magenta : epee::log_space::console_color_green, false)
|
||||||
|
<< transfer.time
|
||||||
|
<< ", " << (transfer.output ? "OUTPUT" : "INPUT")
|
||||||
|
<< ", " << transfer.transactionHash
|
||||||
|
<< ", " << m_currency.formatAmount(transfer.amount)
|
||||||
|
<< ", " << m_currency.formatAmount(transfer.fee)
|
||||||
|
<< ", " << transfer.paymentId
|
||||||
|
<< ", " << address
|
||||||
|
<< ", " << transfer.blockIndex
|
||||||
|
<< ", " << transfer.unlockTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool simple_wallet::show_payments(const std::vector<std::string> &args)
|
bool simple_wallet::show_payments(const std::vector<std::string> &args)
|
||||||
{
|
{
|
||||||
if(args.empty())
|
if(args.empty())
|
||||||
{
|
{
|
||||||
fail_msg_writer() << "expected at least one payment_id";
|
fail_msg_writer() << "expected at least one payment ID";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -819,7 +857,7 @@ bool simple_wallet::show_payments(const std::vector<std::string> &args)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fail_msg_writer() << "payment id has invalid format: \"" << arg << "\", expected 64-character string";
|
fail_msg_writer() << "payment ID has invalid format: \"" << arg << "\", expected 64-character string";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -864,6 +902,13 @@ bool simple_wallet::transfer(const std::vector<std::string> &args)
|
||||||
cryptonote::Transaction tx;
|
cryptonote::Transaction tx;
|
||||||
m_wallet->transfer(cmd.dsts, cmd.fake_outs_count, 0, cmd.fee, cmd.extra, tx);
|
m_wallet->transfer(cmd.dsts, cmd.fake_outs_count, 0, cmd.fee, cmd.extra, tx);
|
||||||
success_msg_writer(true) << "Money successfully sent, transaction " << get_transaction_hash(tx);
|
success_msg_writer(true) << "Money successfully sent, transaction " << get_transaction_hash(tx);
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_wallet->store();
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
fail_msg_writer() << e.what();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (const tools::error::daemon_busy&)
|
catch (const tools::error::daemon_busy&)
|
||||||
{
|
{
|
||||||
|
|
|
@ -62,14 +62,16 @@ namespace cryptonote
|
||||||
bool help(const std::vector<std::string> &args = std::vector<std::string>());
|
bool help(const std::vector<std::string> &args = std::vector<std::string>());
|
||||||
bool start_mining(const std::vector<std::string> &args);
|
bool start_mining(const std::vector<std::string> &args);
|
||||||
bool stop_mining(const std::vector<std::string> &args);
|
bool stop_mining(const std::vector<std::string> &args);
|
||||||
bool refresh(const std::vector<std::string> &args);
|
bool refresh(const std::vector<std::string> &args = std::vector<std::string>());
|
||||||
bool show_balance(const std::vector<std::string> &args = std::vector<std::string>());
|
bool show_balance(const std::vector<std::string> &args = std::vector<std::string>());
|
||||||
bool show_incoming_transfers(const std::vector<std::string> &args);
|
bool show_incoming_transfers(const std::vector<std::string> &args);
|
||||||
bool show_payments(const std::vector<std::string> &args);
|
bool show_payments(const std::vector<std::string> &args);
|
||||||
bool show_blockchain_height(const std::vector<std::string> &args);
|
bool show_blockchain_height(const std::vector<std::string> &args);
|
||||||
|
bool listTransfers(const std::vector<std::string> &args);
|
||||||
bool transfer(const std::vector<std::string> &args);
|
bool transfer(const std::vector<std::string> &args);
|
||||||
bool print_address(const std::vector<std::string> &args = std::vector<std::string>());
|
bool print_address(const std::vector<std::string> &args = std::vector<std::string>());
|
||||||
bool save(const std::vector<std::string> &args);
|
bool save(const std::vector<std::string> &args);
|
||||||
|
bool reset(const std::vector<std::string> &args);
|
||||||
bool set_log(const std::vector<std::string> &args);
|
bool set_log(const std::vector<std::string> &args);
|
||||||
|
|
||||||
uint64_t get_daemon_blockchain_height(std::string& err);
|
uint64_t get_daemon_blockchain_height(std::string& err);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#define BUILD_COMMIT_ID "@VERSION@"
|
#define BUILD_COMMIT_ID "@VERSION@"
|
||||||
#define PROJECT_VERSION "1.0.1"
|
#define PROJECT_VERSION "1.0.2"
|
||||||
#define PROJECT_VERSION_BUILD_NO "316"
|
#define PROJECT_VERSION_BUILD_NO "336"
|
||||||
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO "(" BUILD_COMMIT_ID ")"
|
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO "(" BUILD_COMMIT_ID ")"
|
||||||
|
|
|
@ -74,7 +74,7 @@ WalletTransactionSender::WalletTransactionSender(const cryptonote::Currency& cur
|
||||||
m_unconfirmedTransactions(unconfirmedTransactions),
|
m_unconfirmedTransactions(unconfirmedTransactions),
|
||||||
m_isInitialized(false),
|
m_isInitialized(false),
|
||||||
m_isStoping(false) {
|
m_isStoping(false) {
|
||||||
m_upperTransactionSizeLimit = (cryptonote::parameters::CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 * 125) / 100 - m_currency.minerTxBlobReservedSize();
|
m_upperTransactionSizeLimit = m_currency.blockGrantedFullRewardZone() * 125 / 100 - m_currency.minerTxBlobReservedSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WalletTransactionSender::init(cryptonote::account_keys keys) {
|
void WalletTransactionSender::init(cryptonote::account_keys keys) {
|
||||||
|
|
|
@ -65,7 +65,7 @@ void wallet2::init(const std::string& daemon_address)
|
||||||
m_daemon_address = daemon_address;
|
m_daemon_address = daemon_address;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
bool wallet2::processNewTransaction(TxQueue& queue, const cryptonote::Transaction& tx, uint64_t height, const crypto::hash& bl_id) {
|
bool wallet2::processNewTransaction(TxQueue& queue, const cryptonote::Transaction& tx, uint64_t height, uint64_t time, const crypto::hash& bl_id) {
|
||||||
process_unconfirmed(tx);
|
process_unconfirmed(tx);
|
||||||
|
|
||||||
std::vector<tx_extra_field> tx_extra_fields;
|
std::vector<tx_extra_field> tx_extra_fields;
|
||||||
|
@ -84,7 +84,7 @@ bool wallet2::processNewTransaction(TxQueue& queue, const cryptonote::Transactio
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TxItem txItem = { tx, height, bl_id, pub_key_field.pub_key, std::move(tx_extra_fields) };
|
TxItem txItem = { tx, time, height, bl_id, pub_key_field.pub_key, std::move(tx_extra_fields) };
|
||||||
queue.push(std::unique_ptr<TxItem>(new TxItem(std::move(txItem))));
|
queue.push(std::unique_ptr<TxItem>(new TxItem(std::move(txItem))));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -159,26 +159,59 @@ void wallet2::processCheckedTransaction(const TxItem& item) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tx_extra_nonce extra_nonce;
|
crypto::hash transactionHash = get_transaction_hash(tx);
|
||||||
if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce))
|
|
||||||
{
|
bool ownTransfer = false;
|
||||||
crypto::hash payment_id;
|
for (Transfer& transfer : transfers) {
|
||||||
if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
|
if (transfer.transactionHash == transactionHash) {
|
||||||
{
|
transfer.blockIndex = height;
|
||||||
uint64_t received = (tx_money_spent_in_ins < tx_money_got_in_outs) ? tx_money_got_in_outs - tx_money_spent_in_ins : 0;
|
ownTransfer = true;
|
||||||
if (0 < received && null_hash != payment_id)
|
|
||||||
{
|
|
||||||
payment_details payment;
|
|
||||||
payment.m_tx_hash = cryptonote::get_transaction_hash(tx);
|
|
||||||
payment.m_amount = received;
|
|
||||||
payment.m_block_height = height;
|
|
||||||
payment.m_unlock_time = tx.unlockTime;
|
|
||||||
m_payments.emplace(payment_id, payment);
|
|
||||||
LOG_PRINT_L2("Payment found: " << payment_id << " / " << payment.m_tx_hash << " / " << payment.m_amount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ownTransfer) {
|
||||||
|
crypto::hash paymentId = null_hash;
|
||||||
|
tx_extra_nonce extraNonce;
|
||||||
|
if (find_tx_extra_field_by_type(tx_extra_fields, extraNonce)) {
|
||||||
|
get_payment_id_from_tx_extra_nonce(extraNonce.nonce, paymentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tx_money_spent_in_ins < tx_money_got_in_outs) {
|
||||||
|
if (paymentId != null_hash) {
|
||||||
|
payment_details payment;
|
||||||
|
payment.m_tx_hash = transactionHash;
|
||||||
|
payment.m_amount = tx_money_got_in_outs - tx_money_spent_in_ins;
|
||||||
|
payment.m_block_height = height;
|
||||||
|
payment.m_unlock_time = tx.unlockTime;
|
||||||
|
m_payments.emplace(paymentId, payment);
|
||||||
|
LOG_PRINT_L2("Payment found: " << paymentId << " / " << payment.m_tx_hash << " / " << payment.m_amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
Transfer transfer;
|
||||||
|
transfer.time = item.time;
|
||||||
|
transfer.output = false;
|
||||||
|
transfer.transactionHash = transactionHash;
|
||||||
|
transfer.amount = tx_money_got_in_outs - tx_money_spent_in_ins;
|
||||||
|
transfer.fee = 0;
|
||||||
|
transfer.paymentId = paymentId;
|
||||||
|
transfer.hasAddress = false;
|
||||||
|
transfer.blockIndex = height;
|
||||||
|
transfer.unlockTime = tx.unlockTime;
|
||||||
|
transfers.push_back(transfer);
|
||||||
|
} else if (tx_money_got_in_outs < tx_money_spent_in_ins) {
|
||||||
|
Transfer transfer;
|
||||||
|
transfer.time = item.time;
|
||||||
|
transfer.output = true;
|
||||||
|
transfer.transactionHash = transactionHash;
|
||||||
|
transfer.amount = tx_money_spent_in_ins - tx_money_got_in_outs;
|
||||||
|
transfer.fee = 0;
|
||||||
|
transfer.paymentId = paymentId;
|
||||||
|
transfer.hasAddress = false;
|
||||||
|
transfer.blockIndex = height;
|
||||||
|
transfer.unlockTime = tx.unlockTime;
|
||||||
|
transfers.push_back(transfer);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
@ -211,7 +244,6 @@ bool wallet2::addNewBlockchainEntry(const crypto::hash& bl_id, uint64_t start_he
|
||||||
"current_index=" + std::to_string(current_index) + ", m_blockchain.size()=" + std::to_string(m_blockchain.size()));
|
"current_index=" + std::to_string(current_index) + ", m_blockchain.size()=" + std::to_string(m_blockchain.size()));
|
||||||
|
|
||||||
m_blockchain.push_back(bl_id);
|
m_blockchain.push_back(bl_id);
|
||||||
++m_local_bc_height;
|
|
||||||
|
|
||||||
if (0 != m_callback) {
|
if (0 != m_callback) {
|
||||||
m_callback->on_new_block(current_index);
|
m_callback->on_new_block(current_index);
|
||||||
|
@ -234,7 +266,7 @@ size_t wallet2::processNewBlockchainEntry(TxQueue& queue, const cryptonote::bloc
|
||||||
if (b.timestamp + 60 * 60 * 24 > m_account.get_createtime())
|
if (b.timestamp + 60 * 60 * 24 > m_account.get_createtime())
|
||||||
{
|
{
|
||||||
TIME_MEASURE_START(miner_tx_handle_time);
|
TIME_MEASURE_START(miner_tx_handle_time);
|
||||||
if(processNewTransaction(queue, b.minerTx, height, bl_id))
|
if(processNewTransaction(queue, b.minerTx, height, b.timestamp, bl_id))
|
||||||
++processedTransactions;
|
++processedTransactions;
|
||||||
TIME_MEASURE_FINISH(miner_tx_handle_time);
|
TIME_MEASURE_FINISH(miner_tx_handle_time);
|
||||||
|
|
||||||
|
@ -244,7 +276,7 @@ size_t wallet2::processNewBlockchainEntry(TxQueue& queue, const cryptonote::bloc
|
||||||
cryptonote::Transaction tx;
|
cryptonote::Transaction tx;
|
||||||
bool r = parse_and_validate_tx_from_blob(txblob, tx);
|
bool r = parse_and_validate_tx_from_blob(txblob, tx);
|
||||||
THROW_WALLET_EXCEPTION_IF(!r, error::tx_parse_error, txblob);
|
THROW_WALLET_EXCEPTION_IF(!r, error::tx_parse_error, txblob);
|
||||||
if(processNewTransaction(queue, tx, height, bl_id))
|
if(processNewTransaction(queue, tx, height, b.timestamp, bl_id))
|
||||||
++processedTransactions;
|
++processedTransactions;
|
||||||
}
|
}
|
||||||
TIME_MEASURE_FINISH(txs_handle_time);
|
TIME_MEASURE_FINISH(txs_handle_time);
|
||||||
|
@ -512,7 +544,6 @@ size_t wallet2::detach_blockchain(uint64_t height)
|
||||||
|
|
||||||
size_t blocks_detached = m_blockchain.end() - (m_blockchain.begin()+height);
|
size_t blocks_detached = m_blockchain.end() - (m_blockchain.begin()+height);
|
||||||
m_blockchain.erase(m_blockchain.begin()+height, m_blockchain.end());
|
m_blockchain.erase(m_blockchain.begin()+height, m_blockchain.end());
|
||||||
m_local_bc_height -= blocks_detached;
|
|
||||||
|
|
||||||
for (auto it = m_payments.begin(); it != m_payments.end(); )
|
for (auto it = m_payments.begin(); it != m_payments.end(); )
|
||||||
{
|
{
|
||||||
|
@ -522,6 +553,14 @@ size_t wallet2::detach_blockchain(uint64_t height)
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (std::size_t transferIndex = 0; transferIndex < transfers.size();) {
|
||||||
|
if (transfers[transferIndex].blockIndex != 0 && transfers[transferIndex].blockIndex >= height) {
|
||||||
|
transfers.erase(transfers.begin() + transferIndex);
|
||||||
|
} else {
|
||||||
|
++transferIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LOG_PRINT_L0("Detached blockchain on height " << height << ", transfers detached " << transfers_detached << ", blocks detached " << blocks_detached);
|
LOG_PRINT_L0("Detached blockchain on height " << height << ", transfers detached " << transfers_detached << ", blocks detached " << blocks_detached);
|
||||||
return blocks_detached;
|
return blocks_detached;
|
||||||
}
|
}
|
||||||
|
@ -536,7 +575,6 @@ bool wallet2::clear()
|
||||||
m_blockchain.clear();
|
m_blockchain.clear();
|
||||||
m_transfers.clear();
|
m_transfers.clear();
|
||||||
m_blockchain.push_back(m_currency.genesisBlockHash());
|
m_blockchain.push_back(m_currency.genesisBlockHash());
|
||||||
m_local_bc_height = 1;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
@ -702,8 +740,6 @@ void wallet2::load(const std::string& wallet_, const std::string& password)
|
||||||
THROW_WALLET_EXCEPTION_IF(m_blockchain[0] != m_currency.genesisBlockHash(), error::wallet_internal_error,
|
THROW_WALLET_EXCEPTION_IF(m_blockchain[0] != m_currency.genesisBlockHash(), error::wallet_internal_error,
|
||||||
"Genesis block missmatch. You probably use wallet without testnet flag with blockchain from test network or vice versa");
|
"Genesis block missmatch. You probably use wallet without testnet flag with blockchain from test network or vice versa");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_local_bc_height = m_blockchain.size();
|
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::store()
|
void wallet2::store()
|
||||||
|
@ -852,4 +888,23 @@ void wallet2::transfer(const std::vector<cryptonote::tx_destination_entry>& dsts
|
||||||
transfer(dsts, fake_outputs_count, unlock_time, fee, extra, tx);
|
transfer(dsts, fake_outputs_count, unlock_time, fee, extra, tx);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
const std::vector<wallet2::Transfer>& wallet2::getTransfers() {
|
||||||
|
return transfers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wallet2::reset() {
|
||||||
|
clear();
|
||||||
|
m_unconfirmed_txs.clear();
|
||||||
|
m_payments.clear();
|
||||||
|
m_key_images.clear();
|
||||||
|
for (std::size_t transferIndex = 0; transferIndex < transfers.size();) {
|
||||||
|
if (transfers[transferIndex].hasAddress) {
|
||||||
|
transfers[transferIndex].blockIndex = 0;
|
||||||
|
++transferIndex;
|
||||||
|
} else {
|
||||||
|
transfers.erase(transfers.begin() + transferIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,14 +70,12 @@ namespace tools
|
||||||
wallet2(const wallet2& rhs) :
|
wallet2(const wallet2& rhs) :
|
||||||
m_currency(rhs.m_currency),
|
m_currency(rhs.m_currency),
|
||||||
m_run(true),
|
m_run(true),
|
||||||
m_callback(0),
|
m_callback(0) {
|
||||||
m_upper_transaction_size_limit(rhs.m_upper_transaction_size_limit) {
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wallet2(const cryptonote::Currency& currency) :
|
wallet2(const cryptonote::Currency& currency) :
|
||||||
m_currency(currency), m_run(true), m_callback(0) {
|
m_currency(currency), m_run(true), m_callback(0) {
|
||||||
m_upper_transaction_size_limit = (cryptonote::parameters::CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 * 125) / 100 - m_currency.minerTxBlobReservedSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct transfer_details
|
struct transfer_details
|
||||||
|
@ -121,6 +119,37 @@ namespace tools
|
||||||
END_SERIALIZE()
|
END_SERIALIZE()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Transfer {
|
||||||
|
uint64_t time;
|
||||||
|
bool output;
|
||||||
|
crypto::hash transactionHash;
|
||||||
|
uint64_t amount;
|
||||||
|
uint64_t fee;
|
||||||
|
crypto::hash paymentId;
|
||||||
|
bool hasAddress;
|
||||||
|
cryptonote::AccountPublicAddress address;
|
||||||
|
uint64_t blockIndex;
|
||||||
|
uint64_t unlockTime;
|
||||||
|
|
||||||
|
template <class Archive> void serialize(Archive& archive, unsigned int version) {
|
||||||
|
archive & time;
|
||||||
|
archive & output;
|
||||||
|
archive & transactionHash;
|
||||||
|
archive & amount;
|
||||||
|
archive & fee;
|
||||||
|
archive & paymentId;
|
||||||
|
archive & hasAddress;
|
||||||
|
if (hasAddress) {
|
||||||
|
archive & address;
|
||||||
|
}
|
||||||
|
|
||||||
|
archive & blockIndex;
|
||||||
|
archive & unlockTime;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<Transfer> Transfers;
|
||||||
|
|
||||||
void generate(const std::string& wallet, const std::string& password);
|
void generate(const std::string& wallet, const std::string& password);
|
||||||
void load(const std::string& wallet, const std::string& password);
|
void load(const std::string& wallet, const std::string& password);
|
||||||
void store();
|
void store();
|
||||||
|
@ -153,7 +182,10 @@ namespace tools
|
||||||
bool connectClient(epee::net_utils::http::http_simple_client& client);
|
bool connectClient(epee::net_utils::http::http_simple_client& client);
|
||||||
void get_transfers(wallet2::transfer_container& incoming_transfers) const;
|
void get_transfers(wallet2::transfer_container& incoming_transfers) const;
|
||||||
void get_payments(const crypto::hash& payment_id, std::list<wallet2::payment_details>& payments) const;
|
void get_payments(const crypto::hash& payment_id, std::list<wallet2::payment_details>& payments) const;
|
||||||
uint64_t get_blockchain_current_height() const { return m_local_bc_height; }
|
uint64_t get_blockchain_current_height() const { return m_blockchain.size(); }
|
||||||
|
const std::vector<Transfer>& getTransfers();
|
||||||
|
void reset();
|
||||||
|
|
||||||
template <class t_archive>
|
template <class t_archive>
|
||||||
inline void serialize(t_archive &a, const unsigned int ver)
|
inline void serialize(t_archive &a, const unsigned int ver)
|
||||||
{
|
{
|
||||||
|
@ -169,6 +201,9 @@ namespace tools
|
||||||
if(ver < 7)
|
if(ver < 7)
|
||||||
return;
|
return;
|
||||||
a & m_payments;
|
a & m_payments;
|
||||||
|
if (ver >= 8) {
|
||||||
|
a & transfers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exists);
|
static void wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exists);
|
||||||
|
@ -180,6 +215,7 @@ namespace tools
|
||||||
|
|
||||||
struct TxItem {
|
struct TxItem {
|
||||||
cryptonote::Transaction tx;
|
cryptonote::Transaction tx;
|
||||||
|
uint64_t time;
|
||||||
uint64_t height;
|
uint64_t height;
|
||||||
crypto::hash blockId;
|
crypto::hash blockId;
|
||||||
crypto::public_key txPubKey;
|
crypto::public_key txPubKey;
|
||||||
|
@ -196,7 +232,7 @@ namespace tools
|
||||||
bool addNewBlockchainEntry(const crypto::hash& bl_id, uint64_t start_height, uint64_t height);
|
bool addNewBlockchainEntry(const crypto::hash& bl_id, uint64_t start_height, uint64_t height);
|
||||||
|
|
||||||
size_t processNewBlockchainEntry(TxQueue& queue, const cryptonote::block_complete_entry& bche, const crypto::hash& bl_id, uint64_t height);
|
size_t processNewBlockchainEntry(TxQueue& queue, const cryptonote::block_complete_entry& bche, const crypto::hash& bl_id, uint64_t height);
|
||||||
bool processNewTransaction(TxQueue& queue, const cryptonote::Transaction& tx, uint64_t height, const crypto::hash& bl_id);
|
bool processNewTransaction(TxQueue& queue, const cryptonote::Transaction& tx, uint64_t height, uint64_t time, const crypto::hash& bl_id);
|
||||||
void processCheckedTransaction(const TxItem& item);
|
void processCheckedTransaction(const TxItem& item);
|
||||||
|
|
||||||
// returns number of blocks added
|
// returns number of blocks added
|
||||||
|
@ -234,21 +270,21 @@ namespace tools
|
||||||
std::string m_keys_file;
|
std::string m_keys_file;
|
||||||
epee::net_utils::http::http_simple_client m_http_client;
|
epee::net_utils::http::http_simple_client m_http_client;
|
||||||
std::vector<crypto::hash> m_blockchain;
|
std::vector<crypto::hash> m_blockchain;
|
||||||
std::atomic<uint64_t> m_local_bc_height; //temporary workaround
|
|
||||||
std::unordered_map<crypto::hash, unconfirmed_transfer_details> m_unconfirmed_txs;
|
std::unordered_map<crypto::hash, unconfirmed_transfer_details> m_unconfirmed_txs;
|
||||||
|
|
||||||
transfer_container m_transfers;
|
transfer_container m_transfers;
|
||||||
payment_container m_payments;
|
payment_container m_payments;
|
||||||
std::unordered_map<crypto::key_image, size_t> m_key_images;
|
std::unordered_map<crypto::key_image, size_t> m_key_images;
|
||||||
cryptonote::AccountPublicAddress m_account_public_address;
|
cryptonote::AccountPublicAddress m_account_public_address;
|
||||||
uint64_t m_upper_transaction_size_limit; //TODO: auto-calc this value or request from daemon, now use some fixed value
|
|
||||||
|
|
||||||
std::atomic<bool> m_run;
|
std::atomic<bool> m_run;
|
||||||
|
|
||||||
i_wallet2_callback* m_callback;
|
i_wallet2_callback* m_callback;
|
||||||
|
|
||||||
|
Transfers transfers;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
BOOST_CLASS_VERSION(tools::wallet2, 7)
|
BOOST_CLASS_VERSION(tools::wallet2, 8)
|
||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
|
@ -466,7 +502,8 @@ namespace tools
|
||||||
|
|
||||||
bool r = cryptonote::construct_tx(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time);
|
bool r = cryptonote::construct_tx(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time);
|
||||||
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, m_currency.publicAddressBase58Prefix(), sources, splitted_dsts, unlock_time);
|
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, m_currency.publicAddressBase58Prefix(), sources, splitted_dsts, unlock_time);
|
||||||
THROW_WALLET_EXCEPTION_IF(m_upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, m_upper_transaction_size_limit);
|
uint64_t transactionSizeLimit = m_currency.blockGrantedFullRewardZone() * 125 / 100 - m_currency.minerTxBlobReservedSize();
|
||||||
|
THROW_WALLET_EXCEPTION_IF(get_object_blobsize(tx) > transactionSizeLimit, error::tx_too_big, tx, transactionSizeLimit);
|
||||||
|
|
||||||
std::string key_images;
|
std::string key_images;
|
||||||
bool all_are_txin_to_key = std::all_of(tx.vin.begin(), tx.vin.end(), [&](const TransactionInput& s_e) -> bool
|
bool all_are_txin_to_key = std::all_of(tx.vin.begin(), tx.vin.end(), [&](const TransactionInput& s_e) -> bool
|
||||||
|
@ -487,12 +524,37 @@ namespace tools
|
||||||
|
|
||||||
add_unconfirmed_tx(tx, change_dts.amount);
|
add_unconfirmed_tx(tx, change_dts.amount);
|
||||||
|
|
||||||
LOG_PRINT_L2("transaction " << get_transaction_hash(tx) << " generated ok and sent to daemon, key_images: [" << key_images << "]");
|
crypto::hash transactionHash = get_transaction_hash(tx);
|
||||||
|
LOG_PRINT_L2("transaction " << transactionHash << " generated ok and sent to daemon, key_images: [" << key_images << "]");
|
||||||
|
|
||||||
BOOST_FOREACH(transfer_container::iterator it, selected_transfers)
|
BOOST_FOREACH(transfer_container::iterator it, selected_transfers)
|
||||||
it->m_spent = true;
|
it->m_spent = true;
|
||||||
|
|
||||||
LOG_PRINT_L0("Transaction successfully sent. <" << get_transaction_hash(tx) << ">" << ENDL
|
crypto::hash paymentId = null_hash;
|
||||||
|
std::vector<tx_extra_field> transactionExtras;
|
||||||
|
if (parse_tx_extra(tx.extra, transactionExtras)) {
|
||||||
|
tx_extra_nonce extraNonce;
|
||||||
|
if (find_tx_extra_field_by_type(transactionExtras, extraNonce)) {
|
||||||
|
get_payment_id_from_tx_extra_nonce(extraNonce.nonce, paymentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& destination : dsts) {
|
||||||
|
Transfer transfer;
|
||||||
|
transfer.time = static_cast<uint64_t>(time(NULL));
|
||||||
|
transfer.output = true;
|
||||||
|
transfer.transactionHash = transactionHash;
|
||||||
|
transfer.amount = destination.amount;
|
||||||
|
transfer.fee = fee;
|
||||||
|
transfer.paymentId = paymentId;
|
||||||
|
transfer.hasAddress = true;
|
||||||
|
transfer.address = destination.addr;
|
||||||
|
transfer.blockIndex = 0;
|
||||||
|
transfer.unlockTime = unlock_time;
|
||||||
|
transfers.push_back(transfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_PRINT_L0("Transaction successfully sent. <" << transactionHash << ">" << ENDL
|
||||||
<< "Commission: " << m_currency.formatAmount(fee+dust) << " (dust: " << m_currency.formatAmount(dust) << ")" << ENDL
|
<< "Commission: " << m_currency.formatAmount(fee+dust) << " (dust: " << m_currency.formatAmount(dust) << ")" << ENDL
|
||||||
<< "Balance: " << m_currency.formatAmount(balance()) << ENDL
|
<< "Balance: " << m_currency.formatAmount(balance()) << ENDL
|
||||||
<< "Unlocked: " << m_currency.formatAmount(unlocked_balance()) << ENDL
|
<< "Unlocked: " << m_currency.formatAmount(unlocked_balance()) << ENDL
|
||||||
|
|
|
@ -46,9 +46,16 @@ namespace tools
|
||||||
m_net_server.add_idle_handler([this](){
|
m_net_server.add_idle_handler([this](){
|
||||||
try {
|
try {
|
||||||
m_wallet.refresh();
|
m_wallet.refresh();
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& e) {
|
||||||
LOG_ERROR("Exception at while refreshing, what=" << ex.what());
|
LOG_ERROR("Exception while refreshing, what=" << e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_wallet.store();
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
LOG_ERROR("Exception while storing, what=" << e.what());
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}, 20000);
|
}, 20000);
|
||||||
|
|
||||||
|
@ -192,5 +199,34 @@ namespace tools
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
bool wallet_rpc_server::on_get_transfers(const wallet_rpc::COMMAND_RPC_GET_TRANSFERS::request& req, wallet_rpc::COMMAND_RPC_GET_TRANSFERS::response& res, epee::json_rpc::error& er, connection_context& cntx) {
|
||||||
|
res.transfers.clear();
|
||||||
|
const std::vector<wallet2::Transfer>& transfers = m_wallet.getTransfers();
|
||||||
|
for (const tools::wallet2::Transfer& transfer : transfers) {
|
||||||
|
wallet_rpc::Transfer transfer2;
|
||||||
|
transfer2.time = transfer.time;
|
||||||
|
transfer2.output = transfer.output;
|
||||||
|
transfer2.transactionHash = epee::string_tools::pod_to_hex(transfer.transactionHash);
|
||||||
|
transfer2.amount = transfer.amount;
|
||||||
|
transfer2.fee = transfer.fee;
|
||||||
|
transfer2.paymentId = transfer.paymentId == cryptonote::null_hash ? "" : epee::string_tools::pod_to_hex(transfer.paymentId);
|
||||||
|
transfer2.address = transfer.hasAddress ? getAccountAddressAsStr(m_wallet.currency().publicAddressBase58Prefix(), transfer.address) : "";
|
||||||
|
transfer2.blockIndex = transfer.blockIndex;
|
||||||
|
transfer2.unlockTime = transfer.unlockTime;
|
||||||
|
res.transfers.push_back(transfer2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wallet_rpc_server::on_get_height(const wallet_rpc::COMMAND_RPC_GET_HEIGHT::request& req, wallet_rpc::COMMAND_RPC_GET_HEIGHT::response& res, epee::json_rpc::error& er, connection_context& cntx) {
|
||||||
|
res.height = m_wallet.get_blockchain_current_height();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wallet_rpc_server::on_reset(const wallet_rpc::COMMAND_RPC_RESET::request& req, wallet_rpc::COMMAND_RPC_RESET::response& res, epee::json_rpc::error& er, connection_context& cntx) {
|
||||||
|
m_wallet.reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,9 @@ namespace tools
|
||||||
MAP_JON_RPC_WE("transfer", on_transfer, wallet_rpc::COMMAND_RPC_TRANSFER)
|
MAP_JON_RPC_WE("transfer", on_transfer, wallet_rpc::COMMAND_RPC_TRANSFER)
|
||||||
MAP_JON_RPC_WE("store", on_store, wallet_rpc::COMMAND_RPC_STORE)
|
MAP_JON_RPC_WE("store", on_store, wallet_rpc::COMMAND_RPC_STORE)
|
||||||
MAP_JON_RPC_WE("get_payments", on_get_payments, wallet_rpc::COMMAND_RPC_GET_PAYMENTS)
|
MAP_JON_RPC_WE("get_payments", on_get_payments, wallet_rpc::COMMAND_RPC_GET_PAYMENTS)
|
||||||
|
MAP_JON_RPC_WE("get_transfers", on_get_transfers, wallet_rpc::COMMAND_RPC_GET_TRANSFERS)
|
||||||
|
MAP_JON_RPC_WE("get_height", on_get_height, wallet_rpc::COMMAND_RPC_GET_HEIGHT)
|
||||||
|
MAP_JON_RPC_WE("reset", on_reset, wallet_rpc::COMMAND_RPC_RESET)
|
||||||
END_JSON_RPC_MAP()
|
END_JSON_RPC_MAP()
|
||||||
END_URI_MAP2()
|
END_URI_MAP2()
|
||||||
|
|
||||||
|
@ -60,6 +63,9 @@ namespace tools
|
||||||
bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||||
bool on_store(const wallet_rpc::COMMAND_RPC_STORE::request& req, wallet_rpc::COMMAND_RPC_STORE::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
bool on_store(const wallet_rpc::COMMAND_RPC_STORE::request& req, wallet_rpc::COMMAND_RPC_STORE::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||||
bool on_get_payments(const wallet_rpc::COMMAND_RPC_GET_PAYMENTS::request& req, wallet_rpc::COMMAND_RPC_GET_PAYMENTS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
bool on_get_payments(const wallet_rpc::COMMAND_RPC_GET_PAYMENTS::request& req, wallet_rpc::COMMAND_RPC_GET_PAYMENTS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||||
|
bool on_get_transfers(const wallet_rpc::COMMAND_RPC_GET_TRANSFERS::request& req, wallet_rpc::COMMAND_RPC_GET_TRANSFERS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||||
|
bool on_get_height(const wallet_rpc::COMMAND_RPC_GET_HEIGHT::request& req, wallet_rpc::COMMAND_RPC_GET_HEIGHT::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||||
|
bool on_reset(const wallet_rpc::COMMAND_RPC_RESET::request& req, wallet_rpc::COMMAND_RPC_RESET::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||||
|
|
||||||
bool handle_command_line(const boost::program_options::variables_map& vm);
|
bool handle_command_line(const boost::program_options::variables_map& vm);
|
||||||
|
|
||||||
|
|
|
@ -136,5 +136,71 @@ namespace wallet_rpc
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Transfer {
|
||||||
|
uint64_t time;
|
||||||
|
bool output;
|
||||||
|
std::string transactionHash;
|
||||||
|
uint64_t amount;
|
||||||
|
uint64_t fee;
|
||||||
|
std::string paymentId;
|
||||||
|
std::string address;
|
||||||
|
uint64_t blockIndex;
|
||||||
|
uint64_t unlockTime;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(time)
|
||||||
|
KV_SERIALIZE(output)
|
||||||
|
KV_SERIALIZE(transactionHash)
|
||||||
|
KV_SERIALIZE(amount)
|
||||||
|
KV_SERIALIZE(fee)
|
||||||
|
KV_SERIALIZE(paymentId)
|
||||||
|
KV_SERIALIZE(address)
|
||||||
|
KV_SERIALIZE(blockIndex)
|
||||||
|
KV_SERIALIZE(unlockTime)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct COMMAND_RPC_GET_TRANSFERS {
|
||||||
|
struct request {
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct response {
|
||||||
|
std::list<Transfer> transfers;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(transfers)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct COMMAND_RPC_GET_HEIGHT {
|
||||||
|
struct request {
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct response {
|
||||||
|
uint64_t height;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(height)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct COMMAND_RPC_RESET {
|
||||||
|
struct request {
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct response {
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -591,37 +591,14 @@ bool gen_block_has_invalid_tx::generate(std::vector<test_event_entry>& events) c
|
||||||
bool gen_block_is_too_big::generate(std::vector<test_event_entry>& events) const
|
bool gen_block_is_too_big::generate(std::vector<test_event_entry>& events) const
|
||||||
{
|
{
|
||||||
BLOCK_VALIDATION_INIT_GENERATE();
|
BLOCK_VALIDATION_INIT_GENERATE();
|
||||||
|
generator.defaultMajorVersion = m_blockMajorVersion;
|
||||||
|
|
||||||
// Creating a huge miner_tx, it will have a lot of outs
|
|
||||||
MAKE_MINER_TX_MANUALLY(miner_tx, blk_0);
|
|
||||||
static const size_t tx_out_count = m_currency.blockGrantedFullRewardZone() / 2;
|
|
||||||
uint64_t amount = get_outs_money_amount(miner_tx);
|
|
||||||
uint64_t portion = amount / tx_out_count;
|
|
||||||
uint64_t remainder = amount % tx_out_count;
|
|
||||||
TransactionOutputTarget target = miner_tx.vout[0].target;
|
|
||||||
miner_tx.vout.clear();
|
|
||||||
for (size_t i = 0; i < tx_out_count; ++i)
|
|
||||||
{
|
|
||||||
TransactionOutput o;
|
|
||||||
o.amount = portion;
|
|
||||||
o.target = target;
|
|
||||||
miner_tx.vout.push_back(o);
|
|
||||||
}
|
|
||||||
if (0 < remainder)
|
|
||||||
{
|
|
||||||
TransactionOutput o;
|
|
||||||
o.amount = remainder;
|
|
||||||
o.target = target;
|
|
||||||
miner_tx.vout.push_back(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block reward will be incorrect, as it must be reduced if cumulative block size is very big,
|
|
||||||
// but in this test it doesn't matter
|
|
||||||
Block blk_1;
|
Block blk_1;
|
||||||
if (!generator.constructBlockManually(blk_1, blk_0, miner_account,
|
if (!generator.constructMaxSizeBlock(blk_1, blk_0, miner_account)) {
|
||||||
test_generator::bf_major_ver | test_generator::bf_miner_tx, m_blockMajorVersion, 0, 0, crypto::hash(), 0, miner_tx))
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
blk_1.minerTx.extra.resize(blk_1.minerTx.extra.size() + 1);
|
||||||
events.push_back(blk_1);
|
events.push_back(blk_1);
|
||||||
|
|
||||||
DO_CALLBACK(events, "check_block_purged");
|
DO_CALLBACK(events, "check_block_purged");
|
||||||
|
|
|
@ -297,7 +297,12 @@ struct gen_block_has_invalid_tx : public CheckBlockPurged
|
||||||
struct gen_block_is_too_big : public CheckBlockPurged
|
struct gen_block_is_too_big : public CheckBlockPurged
|
||||||
{
|
{
|
||||||
gen_block_is_too_big(uint8_t blockMajorVersion)
|
gen_block_is_too_big(uint8_t blockMajorVersion)
|
||||||
: CheckBlockPurged(1, blockMajorVersion) {}
|
: CheckBlockPurged(1, blockMajorVersion) {
|
||||||
|
cryptonote::CurrencyBuilder currencyBuilder;
|
||||||
|
currencyBuilder.upgradeHeight(blockMajorVersion == cryptonote::BLOCK_MAJOR_VERSION_1 ? UNDEF_HEIGHT : UINT64_C(0));
|
||||||
|
currencyBuilder.maxBlockSizeInitial(std::numeric_limits<size_t>::max() / 2);
|
||||||
|
m_currency = currencyBuilder.currency();
|
||||||
|
}
|
||||||
|
|
||||||
bool generate(std::vector<test_event_entry>& events) const;
|
bool generate(std::vector<test_event_entry>& events) const;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue