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
|
||||
|
||||
- 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_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 size_t UPGRADE_VOTING_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 uint64_t P2P_DEFAULT_INVOKE_TIMEOUT = 60 * 2 * 1000; // 2 minutes
|
||||
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 unsigned THREAD_STACK_SIZE = 5 * 1024 * 1024;
|
||||
|
@ -143,7 +144,8 @@ const CheckpointData CHECKPOINTS[] = {
|
|||
{480200, "363544ac9920c778b815c2fdbcbca70a0d79b21f662913a42da9b49e859f0e5b"},
|
||||
{484500, "5cdf2101a0a62a0ab2a1ca0c15a6212b21f6dbdc42a0b7c0bcf65ca40b7a14fb"},
|
||||
{506000, "3d54c1132f503d98d3f0d78bb46a4503c1a19447cb348361a2232e241cb45a3c"},
|
||||
{544000, "f69dc61b6a63217f32fa64d5d0f9bd920873f57dfd79ebe1d7d6fb1345b56fe0"}
|
||||
{544000, "f69dc61b6a63217f32fa64d5d0f9bd920873f57dfd79ebe1d7d6fb1345b56fe0"},
|
||||
{553300, "f7a5076b887ce5f4bb95b2729c0edb6f077a463f04f1bffe7f5cb0b16bb8aa5f"}
|
||||
};
|
||||
} // cryptonote
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace cryptonote {
|
|||
CHECK_AND_ASSERT_MES(r, false, "Failed to get genesis block hash");
|
||||
|
||||
if (isTestnet()) {
|
||||
m_upgradeHeight = 0;
|
||||
m_blocksFileName = "testnet_" + m_blocksFileName;
|
||||
m_blocksCacheFileName = "testnet_" + m_blocksCacheFileName;
|
||||
m_blockIndexesFileName = "testnet_" + m_blockIndexesFileName;
|
||||
|
@ -380,7 +381,7 @@ namespace cryptonote {
|
|||
mempoolTxLiveTime(parameters::CRYPTONOTE_MEMPOOL_TX_LIVETIME);
|
||||
mempoolTxFromAltBlockLiveTime(parameters::CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME);
|
||||
|
||||
upgradeHeight(UpgradeDetectorBase::UNDEF_HEIGHT);
|
||||
upgradeHeight(parameters::UPGRADE_HEIGHT);
|
||||
upgradeVotingThreshold(parameters::UPGRADE_VOTING_THRESHOLD);
|
||||
upgradeVotingWindow(parameters::UPGRADE_VOTING_WINDOW);
|
||||
upgradeWindow(parameters::UPGRADE_WINDOW);
|
||||
|
|
|
@ -231,8 +231,9 @@ namespace cryptonote
|
|||
if (version < CURRENT_BLOCKCACHE_STORAGE_ARCHIVE_VER)
|
||||
return;
|
||||
|
||||
std::string operation;
|
||||
if (Archive::is_loading::value) {
|
||||
|
||||
operation = "- loading ";
|
||||
crypto::hash blockHash;
|
||||
ar & blockHash;
|
||||
|
||||
|
@ -241,13 +242,23 @@ namespace cryptonote
|
|||
}
|
||||
|
||||
} else {
|
||||
operation = "- saving ";
|
||||
ar & m_lastBlockHash;
|
||||
}
|
||||
|
||||
LOG_PRINT_L0(operation << "block index...");
|
||||
ar & m_bs.m_blockIndex;
|
||||
|
||||
LOG_PRINT_L0(operation << "transaction map...");
|
||||
ar & m_bs.m_transactionMap;
|
||||
|
||||
LOG_PRINT_L0(operation << "spend keys...");
|
||||
ar & m_bs.m_spent_keys;
|
||||
|
||||
LOG_PRINT_L0(operation << "outputs...");
|
||||
ar & m_bs.m_outputs;
|
||||
|
||||
LOG_PRINT_L0(operation << "multi-signature outputs...");
|
||||
ar & m_bs.m_multisignatureOutputs;
|
||||
|
||||
m_loaded = true;
|
||||
|
@ -377,6 +388,9 @@ bool blockchain_storage::init(const std::string& config_folder, bool load_existi
|
|||
m_outputs.clear();
|
||||
m_multisignatureOutputs.clear();
|
||||
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];
|
||||
crypto::hash blockHash = get_block_hash(block.bl);
|
||||
m_blockIndex.push(blockHash);
|
||||
|
@ -435,6 +449,7 @@ bool blockchain_storage::init(const std::string& config_folder, bool load_existi
|
|||
bool blockchain_storage::storeCache() {
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
|
||||
LOG_PRINT_L0("Saving blockchain...");
|
||||
BlockCacheSerializer ser(*this, get_tail_id());
|
||||
if (!tools::serialize_obj_to_file(ser, appendPath(m_config_folder, m_currency.blocksCacheFileName()))) {
|
||||
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)) {
|
||||
LOG_PRINT_RED_L0("Block with id: " << id
|
||||
<< ENDL << " can't be accepted for alternative chain, block height: " << block_height
|
||||
<< ENDL << " blockchain height: " << get_current_blockchain_height());
|
||||
LOG_PRINT_L2("Block with id: " << id << std::endl <<
|
||||
" can't be accepted for alternative chain, block height: " << block_height << std::endl <<
|
||||
" blockchain height: " << get_current_blockchain_height());
|
||||
bvc.m_verifivation_failed = true;
|
||||
return false;
|
||||
}
|
||||
|
@ -1525,7 +1540,7 @@ bool blockchain_storage::checkBlockVersion(const Block& b, const crypto::hash& b
|
|||
uint64_t height = get_block_height(b);
|
||||
const uint8_t expectedBlockVersion = get_block_major_version_for_height(height);
|
||||
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));
|
||||
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())
|
||||
{
|
||||
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()));
|
||||
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());
|
||||
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) "
|
||||
<< (0 <= diff ? std::string("behind") : std::string("ahead"))
|
||||
<< "] " << ENDL << "SYNCHRONIZATION started", (is_inital ? LOG_LEVEL_0:LOG_LEVEL_1));
|
||||
<< " [" << std::abs(diff) << " blocks (" << std::abs(diff) / (24 * 60 * 60 / m_core.currency().difficultyTarget()) << " days) "
|
||||
<< (diff >= 0 ? std::string("behind") : std::string("ahead")) << "] " << std::endl <<
|
||||
"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);
|
||||
context.m_state = cryptonote_connection_context::state_synchronizing;
|
||||
context.m_remote_blockchain_height = hshd.current_height;
|
||||
|
@ -173,7 +173,7 @@ namespace cryptonote
|
|||
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
||||
m_core.handle_incoming_block_blob(arg.b.block, bvc, true, false);
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
|
@ -332,7 +332,7 @@ namespace cryptonote
|
|||
m_core.handle_incoming_block_blob(block_entry.block, bvc, false, false);
|
||||
|
||||
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);
|
||||
return 1;
|
||||
} else if (bvc.m_marked_as_orphaned) {
|
||||
|
|
|
@ -230,7 +230,7 @@ namespace
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
} else if (arg == "-f") {
|
||||
|
@ -249,7 +249,13 @@ namespace
|
|||
cryptonote::tx_destination_entry de;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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("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("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("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),
|
||||
|
@ -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("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("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");
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
@ -560,7 +568,14 @@ bool simple_wallet::save(const std::vector<std::string> &args)
|
|||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
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())
|
||||
return true;
|
||||
|
@ -776,12 +791,35 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args
|
|||
|
||||
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)
|
||||
{
|
||||
if(args.empty())
|
||||
{
|
||||
fail_msg_writer() << "expected at least one payment_id";
|
||||
fail_msg_writer() << "expected at least one payment ID";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -819,7 +857,7 @@ bool simple_wallet::show_payments(const std::vector<std::string> &args)
|
|||
}
|
||||
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;
|
||||
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);
|
||||
|
||||
try {
|
||||
m_wallet->store();
|
||||
} catch (const std::exception& e) {
|
||||
fail_msg_writer() << e.what();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
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 start_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_incoming_transfers(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 listTransfers(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 save(const std::vector<std::string> &args);
|
||||
bool reset(const std::vector<std::string> &args);
|
||||
bool set_log(const std::vector<std::string> &args);
|
||||
|
||||
uint64_t get_daemon_blockchain_height(std::string& err);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#define BUILD_COMMIT_ID "@VERSION@"
|
||||
#define PROJECT_VERSION "1.0.1"
|
||||
#define PROJECT_VERSION_BUILD_NO "316"
|
||||
#define PROJECT_VERSION "1.0.2"
|
||||
#define PROJECT_VERSION_BUILD_NO "336"
|
||||
#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_isInitialized(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) {
|
||||
|
|
|
@ -65,7 +65,7 @@ void wallet2::init(const std::string& 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);
|
||||
|
||||
std::vector<tx_extra_field> tx_extra_fields;
|
||||
|
@ -84,7 +84,7 @@ bool wallet2::processNewTransaction(TxQueue& queue, const cryptonote::Transactio
|
|||
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))));
|
||||
return true;
|
||||
}
|
||||
|
@ -159,26 +159,59 @@ void wallet2::processCheckedTransaction(const TxItem& item) {
|
|||
}
|
||||
}
|
||||
|
||||
tx_extra_nonce extra_nonce;
|
||||
if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce))
|
||||
{
|
||||
crypto::hash payment_id;
|
||||
if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
|
||||
{
|
||||
uint64_t received = (tx_money_spent_in_ins < tx_money_got_in_outs) ? tx_money_got_in_outs - tx_money_spent_in_ins : 0;
|
||||
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);
|
||||
}
|
||||
crypto::hash transactionHash = get_transaction_hash(tx);
|
||||
|
||||
bool ownTransfer = false;
|
||||
for (Transfer& transfer : transfers) {
|
||||
if (transfer.transactionHash == transactionHash) {
|
||||
transfer.blockIndex = height;
|
||||
ownTransfer = true;
|
||||
}
|
||||
}
|
||||
|
||||
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()));
|
||||
|
||||
m_blockchain.push_back(bl_id);
|
||||
++m_local_bc_height;
|
||||
|
||||
if (0 != m_callback) {
|
||||
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())
|
||||
{
|
||||
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;
|
||||
TIME_MEASURE_FINISH(miner_tx_handle_time);
|
||||
|
||||
|
@ -244,7 +276,7 @@ size_t wallet2::processNewBlockchainEntry(TxQueue& queue, const cryptonote::bloc
|
|||
cryptonote::Transaction tx;
|
||||
bool r = parse_and_validate_tx_from_blob(txblob, tx);
|
||||
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;
|
||||
}
|
||||
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);
|
||||
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(); )
|
||||
{
|
||||
|
@ -522,6 +553,14 @@ size_t wallet2::detach_blockchain(uint64_t height)
|
|||
++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);
|
||||
return blocks_detached;
|
||||
}
|
||||
|
@ -536,7 +575,6 @@ bool wallet2::clear()
|
|||
m_blockchain.clear();
|
||||
m_transfers.clear();
|
||||
m_blockchain.push_back(m_currency.genesisBlockHash());
|
||||
m_local_bc_height = 1;
|
||||
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,
|
||||
"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()
|
||||
|
@ -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);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
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) :
|
||||
m_currency(rhs.m_currency),
|
||||
m_run(true),
|
||||
m_callback(0),
|
||||
m_upper_transaction_size_limit(rhs.m_upper_transaction_size_limit) {
|
||||
m_callback(0) {
|
||||
};
|
||||
|
||||
public:
|
||||
wallet2(const cryptonote::Currency& currency) :
|
||||
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
|
||||
|
@ -121,6 +119,37 @@ namespace tools
|
|||
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 load(const std::string& wallet, const std::string& password);
|
||||
void store();
|
||||
|
@ -153,7 +182,10 @@ namespace tools
|
|||
bool connectClient(epee::net_utils::http::http_simple_client& client);
|
||||
void get_transfers(wallet2::transfer_container& incoming_transfers) 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>
|
||||
inline void serialize(t_archive &a, const unsigned int ver)
|
||||
{
|
||||
|
@ -169,6 +201,9 @@ namespace tools
|
|||
if(ver < 7)
|
||||
return;
|
||||
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);
|
||||
|
@ -180,6 +215,7 @@ namespace tools
|
|||
|
||||
struct TxItem {
|
||||
cryptonote::Transaction tx;
|
||||
uint64_t time;
|
||||
uint64_t height;
|
||||
crypto::hash blockId;
|
||||
crypto::public_key txPubKey;
|
||||
|
@ -196,7 +232,7 @@ namespace tools
|
|||
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);
|
||||
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);
|
||||
|
||||
// returns number of blocks added
|
||||
|
@ -234,21 +270,21 @@ namespace tools
|
|||
std::string m_keys_file;
|
||||
epee::net_utils::http::http_simple_client m_http_client;
|
||||
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;
|
||||
|
||||
transfer_container m_transfers;
|
||||
payment_container m_payments;
|
||||
std::unordered_map<crypto::key_image, size_t> m_key_images;
|
||||
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;
|
||||
|
||||
i_wallet2_callback* m_callback;
|
||||
|
||||
Transfers transfers;
|
||||
};
|
||||
}
|
||||
BOOST_CLASS_VERSION(tools::wallet2, 7)
|
||||
BOOST_CLASS_VERSION(tools::wallet2, 8)
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
@ -466,7 +502,8 @@ namespace tools
|
|||
|
||||
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(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;
|
||||
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);
|
||||
|
||||
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)
|
||||
it->m_spent = true;
|
||||
|
||||
LOG_PRINT_L0("Transaction successfully sent. <" << get_transaction_hash(tx) << ">" << ENDL
|
||||
<< "Commission: " << m_currency.formatAmount(fee + dust) << " (dust: " << m_currency.formatAmount(dust) << ")" << 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
|
||||
<< "Balance: " << m_currency.formatAmount(balance()) << ENDL
|
||||
<< "Unlocked: " << m_currency.formatAmount(unlocked_balance()) << ENDL
|
||||
<< "Please, wait for confirmation for your balance to be unlocked.");
|
||||
|
|
|
@ -46,9 +46,16 @@ namespace tools
|
|||
m_net_server.add_idle_handler([this](){
|
||||
try {
|
||||
m_wallet.refresh();
|
||||
} catch (const std::exception& ex) {
|
||||
LOG_ERROR("Exception at while refreshing, what=" << ex.what());
|
||||
} catch (const std::exception& e) {
|
||||
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;
|
||||
}, 20000);
|
||||
|
||||
|
@ -192,5 +199,34 @@ namespace tools
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,10 +48,13 @@ namespace tools
|
|||
|
||||
BEGIN_URI_MAP2()
|
||||
BEGIN_JSON_RPC_MAP("/json_rpc")
|
||||
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("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("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("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_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_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_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_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);
|
||||
|
||||
|
|
|
@ -136,5 +136,71 @@ namespace wallet_rpc
|
|||
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
|
||||
{
|
||||
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;
|
||||
if (!generator.constructBlockManually(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))
|
||||
if (!generator.constructMaxSizeBlock(blk_1, blk_0, miner_account)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
blk_1.minerTx.extra.resize(blk_1.minerTx.extra.size() + 1);
|
||||
events.push_back(blk_1);
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue