Transaction history and 'reset' command for simplewallet

This commit is contained in:
jezal 2014-08-25 15:35:07 +01:00
parent c3b1a00085
commit 9df3a81801
17 changed files with 376 additions and 98 deletions

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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) {

View file

@ -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&)
{ {

View file

@ -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);

View file

@ -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 ")"

View file

@ -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) {

View file

@ -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);
}
}
}
} }

View file

@ -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,13 +524,38 @@ 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;
<< "Commission: " << m_currency.formatAmount(fee + dust) << " (dust: " << m_currency.formatAmount(dust) << ")" << ENDL 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
<< "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
<< "Please, wait for confirmation for your balance to be unlocked."); << "Please, wait for confirmation for your balance to be unlocked.");

View file

@ -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;
}
} }

View file

@ -48,10 +48,13 @@ namespace tools
BEGIN_URI_MAP2() BEGIN_URI_MAP2()
BEGIN_JSON_RPC_MAP("/json_rpc") BEGIN_JSON_RPC_MAP("/json_rpc")
MAP_JON_RPC_WE("getbalance", on_getbalance, wallet_rpc::COMMAND_RPC_GET_BALANCE) MAP_JON_RPC_WE("getbalance", on_getbalance, wallet_rpc::COMMAND_RPC_GET_BALANCE)
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);

View file

@ -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()
};
};
} }
} }

View file

@ -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");

View file

@ -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;
}; };