Merge pull request #1911
91d41090
tx_pool: ensure txes loaded from poolstate.bin have their txid cached (moneromooo-monero)aaeb164c
tx_pool: remove transactions if they're in the blockchain (moneromooo-monero)558cfc31
core, wallet: faster tx pool scanning (moneromooo-monero)f065234b
core: cache tx and block hashes in the respective classes (moneromooo-monero)
This commit is contained in:
commit
a73a886cb1
|
@ -190,11 +190,24 @@ namespace cryptonote
|
||||||
std::vector<std::vector<crypto::signature> > signatures; //count signatures always the same as inputs count
|
std::vector<std::vector<crypto::signature> > signatures; //count signatures always the same as inputs count
|
||||||
rct::rctSig rct_signatures;
|
rct::rctSig rct_signatures;
|
||||||
|
|
||||||
|
// hash cash
|
||||||
|
mutable crypto::hash hash;
|
||||||
|
mutable size_t blob_size;
|
||||||
|
mutable bool hash_valid;
|
||||||
|
mutable bool blob_size_valid;
|
||||||
|
|
||||||
transaction();
|
transaction();
|
||||||
virtual ~transaction();
|
virtual ~transaction();
|
||||||
void set_null();
|
void set_null();
|
||||||
|
void invalidate_hashes();
|
||||||
|
|
||||||
BEGIN_SERIALIZE_OBJECT()
|
BEGIN_SERIALIZE_OBJECT()
|
||||||
|
if (!typename Archive<W>::is_saving())
|
||||||
|
{
|
||||||
|
hash_valid = false;
|
||||||
|
blob_size_valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
FIELDS(*static_cast<transaction_prefix *>(this))
|
FIELDS(*static_cast<transaction_prefix *>(this))
|
||||||
|
|
||||||
if (version == 1)
|
if (version == 1)
|
||||||
|
@ -299,6 +312,15 @@ namespace cryptonote
|
||||||
extra.clear();
|
extra.clear();
|
||||||
signatures.clear();
|
signatures.clear();
|
||||||
rct_signatures.type = rct::RCTTypeNull;
|
rct_signatures.type = rct::RCTTypeNull;
|
||||||
|
hash_valid = false;
|
||||||
|
blob_size_valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
void transaction::invalidate_hashes()
|
||||||
|
{
|
||||||
|
hash_valid = false;
|
||||||
|
blob_size_valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
|
@ -339,10 +361,20 @@ namespace cryptonote
|
||||||
|
|
||||||
struct block: public block_header
|
struct block: public block_header
|
||||||
{
|
{
|
||||||
|
block(): block_header(), hash_valid(false) {}
|
||||||
|
void invalidate_hashes() { hash_valid = false; }
|
||||||
|
|
||||||
transaction miner_tx;
|
transaction miner_tx;
|
||||||
std::vector<crypto::hash> tx_hashes;
|
std::vector<crypto::hash> tx_hashes;
|
||||||
|
|
||||||
|
// hash cash
|
||||||
|
mutable crypto::hash hash;
|
||||||
|
mutable bool hash_valid;
|
||||||
|
|
||||||
BEGIN_SERIALIZE_OBJECT()
|
BEGIN_SERIALIZE_OBJECT()
|
||||||
|
if (!typename Archive<W>::is_saving())
|
||||||
|
hash_valid = false;
|
||||||
|
|
||||||
FIELDS(*static_cast<block_header *>(this))
|
FIELDS(*static_cast<block_header *>(this))
|
||||||
FIELD(miner_tx)
|
FIELD(miner_tx)
|
||||||
FIELD(tx_hashes)
|
FIELD(tx_hashes)
|
||||||
|
|
|
@ -43,6 +43,8 @@ using namespace epee;
|
||||||
|
|
||||||
#define ENCRYPTED_PAYMENT_ID_TAIL 0x8d
|
#define ENCRYPTED_PAYMENT_ID_TAIL 0x8d
|
||||||
|
|
||||||
|
// #define ENABLE_HASH_CASH_INTEGRITY_CHECK
|
||||||
|
|
||||||
static const uint64_t valid_decomposed_outputs[] = {
|
static const uint64_t valid_decomposed_outputs[] = {
|
||||||
(uint64_t)1, (uint64_t)2, (uint64_t)3, (uint64_t)4, (uint64_t)5, (uint64_t)6, (uint64_t)7, (uint64_t)8, (uint64_t)9, // 1 piconero
|
(uint64_t)1, (uint64_t)2, (uint64_t)3, (uint64_t)4, (uint64_t)5, (uint64_t)6, (uint64_t)7, (uint64_t)8, (uint64_t)9, // 1 piconero
|
||||||
(uint64_t)10, (uint64_t)20, (uint64_t)30, (uint64_t)40, (uint64_t)50, (uint64_t)60, (uint64_t)70, (uint64_t)80, (uint64_t)90,
|
(uint64_t)10, (uint64_t)20, (uint64_t)30, (uint64_t)40, (uint64_t)50, (uint64_t)60, (uint64_t)70, (uint64_t)80, (uint64_t)90,
|
||||||
|
@ -68,6 +70,11 @@ static const uint64_t valid_decomposed_outputs[] = {
|
||||||
|
|
||||||
static std::atomic<unsigned int> default_decimal_point(CRYPTONOTE_DISPLAY_DECIMAL_POINT);
|
static std::atomic<unsigned int> default_decimal_point(CRYPTONOTE_DISPLAY_DECIMAL_POINT);
|
||||||
|
|
||||||
|
static std::atomic<uint64_t> tx_hashes_calculated_count(0);
|
||||||
|
static std::atomic<uint64_t> tx_hashes_cached_count(0);
|
||||||
|
static std::atomic<uint64_t> block_hashes_calculated_count(0);
|
||||||
|
static std::atomic<uint64_t> block_hashes_cached_count(0);
|
||||||
|
|
||||||
namespace cryptonote
|
namespace cryptonote
|
||||||
{
|
{
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
@ -93,6 +100,8 @@ namespace cryptonote
|
||||||
binary_archive<false> ba(ss);
|
binary_archive<false> ba(ss);
|
||||||
bool r = ::serialization::serialize(ba, tx);
|
bool r = ::serialization::serialize(ba, tx);
|
||||||
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
|
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
|
||||||
|
tx.hash_valid = false;
|
||||||
|
tx.blob_size_valid = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
@ -113,6 +122,8 @@ namespace cryptonote
|
||||||
binary_archive<false> ba(ss);
|
binary_archive<false> ba(ss);
|
||||||
bool r = ::serialization::serialize(ba, tx);
|
bool r = ::serialization::serialize(ba, tx);
|
||||||
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
|
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
|
||||||
|
tx.hash_valid = false;
|
||||||
|
tx.blob_size_valid = false;
|
||||||
//TODO: validate tx
|
//TODO: validate tx
|
||||||
|
|
||||||
get_transaction_hash(tx, tx_hash);
|
get_transaction_hash(tx, tx_hash);
|
||||||
|
@ -592,7 +603,7 @@ namespace cryptonote
|
||||||
return get_transaction_hash(t, res, NULL);
|
return get_transaction_hash(t, res, NULL);
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size)
|
bool calculate_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size)
|
||||||
{
|
{
|
||||||
// v1 transactions hash the entire blob
|
// v1 transactions hash the entire blob
|
||||||
if (t.version == 1)
|
if (t.version == 1)
|
||||||
|
@ -647,6 +658,40 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size)
|
||||||
|
{
|
||||||
|
if (t.hash_valid)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_HASH_CASH_INTEGRITY_CHECK
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(!calculate_transaction_hash(t, res, blob_size) || t.hash == res, "tx hash cash integrity failure");
|
||||||
|
#endif
|
||||||
|
res = t.hash;
|
||||||
|
if (blob_size)
|
||||||
|
{
|
||||||
|
if (!t.blob_size_valid)
|
||||||
|
{
|
||||||
|
t.blob_size = get_object_blobsize(t);
|
||||||
|
t.blob_size_valid = true;
|
||||||
|
}
|
||||||
|
*blob_size = t.blob_size;
|
||||||
|
}
|
||||||
|
++tx_hashes_cached_count;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
++tx_hashes_calculated_count;
|
||||||
|
bool ret = calculate_transaction_hash(t, res, blob_size);
|
||||||
|
if (!ret)
|
||||||
|
return false;
|
||||||
|
t.hash = res;
|
||||||
|
t.hash_valid = true;
|
||||||
|
if (blob_size)
|
||||||
|
{
|
||||||
|
t.blob_size = *blob_size;
|
||||||
|
t.blob_size_valid = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------
|
||||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size)
|
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size)
|
||||||
{
|
{
|
||||||
return get_transaction_hash(t, res, &blob_size);
|
return get_transaction_hash(t, res, &blob_size);
|
||||||
|
@ -661,7 +706,7 @@ namespace cryptonote
|
||||||
return blob;
|
return blob;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
bool get_block_hash(const block& b, crypto::hash& res)
|
bool calculate_block_hash(const block& b, crypto::hash& res)
|
||||||
{
|
{
|
||||||
// EXCEPTION FOR BLOCK 202612
|
// EXCEPTION FOR BLOCK 202612
|
||||||
const std::string correct_blob_hash_202612 = "3a8a2b3a29b50fc86ff73dd087ea43c6f0d6b8f936c849194d5c84c737903966";
|
const std::string correct_blob_hash_202612 = "3a8a2b3a29b50fc86ff73dd087ea43c6f0d6b8f936c849194d5c84c737903966";
|
||||||
|
@ -688,6 +733,26 @@ namespace cryptonote
|
||||||
return hash_result;
|
return hash_result;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
bool get_block_hash(const block& b, crypto::hash& res)
|
||||||
|
{
|
||||||
|
if (b.hash_valid)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_HASH_CASH_INTEGRITY_CHECK
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(!calculate_block_hash(b, res) || b.hash == res, "block hash cash integrity failure");
|
||||||
|
#endif
|
||||||
|
res = b.hash;
|
||||||
|
++block_hashes_cached_count;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
++block_hashes_calculated_count;
|
||||||
|
bool ret = calculate_block_hash(b, res);
|
||||||
|
if (!ret)
|
||||||
|
return false;
|
||||||
|
b.hash = res;
|
||||||
|
b.hash_valid = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------
|
||||||
crypto::hash get_block_hash(const block& b)
|
crypto::hash get_block_hash(const block& b)
|
||||||
{
|
{
|
||||||
crypto::hash p = null_hash;
|
crypto::hash p = null_hash;
|
||||||
|
@ -744,6 +809,9 @@ namespace cryptonote
|
||||||
binary_archive<false> ba(ss);
|
binary_archive<false> ba(ss);
|
||||||
bool r = ::serialization::serialize(ba, b);
|
bool r = ::serialization::serialize(ba, b);
|
||||||
CHECK_AND_ASSERT_MES(r, false, "Failed to parse block from blob");
|
CHECK_AND_ASSERT_MES(r, false, "Failed to parse block from blob");
|
||||||
|
b.hash_valid = false;
|
||||||
|
b.miner_tx.hash_valid = false;
|
||||||
|
b.miner_tx.blob_size_valid = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
@ -798,4 +866,11 @@ namespace cryptonote
|
||||||
return std::binary_search(begin, end, amount);
|
return std::binary_search(begin, end, amount);
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
void get_hash_stats(uint64_t &tx_hashes_calculated, uint64_t &tx_hashes_cached, uint64_t &block_hashes_calculated, uint64_t & block_hashes_cached)
|
||||||
|
{
|
||||||
|
tx_hashes_calculated = tx_hashes_calculated_count;
|
||||||
|
tx_hashes_cached = tx_hashes_cached_count;
|
||||||
|
block_hashes_calculated = block_hashes_calculated_count;
|
||||||
|
block_hashes_cached = block_hashes_cached_count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,9 @@ namespace cryptonote
|
||||||
bool get_transaction_hash(const transaction& t, crypto::hash& res);
|
bool get_transaction_hash(const transaction& t, crypto::hash& res);
|
||||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size);
|
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size);
|
||||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size);
|
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size);
|
||||||
|
bool calculate_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size);
|
||||||
blobdata get_block_hashing_blob(const block& b);
|
blobdata get_block_hashing_blob(const block& b);
|
||||||
|
bool calculate_block_hash(const block& b, crypto::hash& res);
|
||||||
bool get_block_hash(const block& b, crypto::hash& res);
|
bool get_block_hash(const block& b, crypto::hash& res);
|
||||||
crypto::hash get_block_hash(const block& b);
|
crypto::hash get_block_hash(const block& b);
|
||||||
bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height);
|
bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height);
|
||||||
|
@ -209,6 +211,7 @@ namespace cryptonote
|
||||||
crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes);
|
crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes);
|
||||||
crypto::hash get_tx_tree_hash(const block& b);
|
crypto::hash get_tx_tree_hash(const block& b);
|
||||||
bool is_valid_decomposed_amount(uint64_t amount);
|
bool is_valid_decomposed_amount(uint64_t amount);
|
||||||
|
void get_hash_stats(uint64_t &tx_hashes_calculated, uint64_t &tx_hashes_cached, uint64_t &block_hashes_calculated, uint64_t & block_hashes_cached);
|
||||||
|
|
||||||
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \
|
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \
|
||||||
CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \
|
CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \
|
||||||
|
|
|
@ -355,9 +355,11 @@ namespace cryptonote
|
||||||
|
|
||||||
if(check_hash(h, diffic))
|
if(check_hash(h, diffic))
|
||||||
{
|
{
|
||||||
|
bl.hash_valid = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bl.hash_valid = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -1037,6 +1037,12 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------
|
||||||
|
bool core::get_pool_transaction_hashes(std::vector<crypto::hash>& txs) const
|
||||||
|
{
|
||||||
|
m_mempool.get_transaction_hashes(txs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------------------------
|
||||||
bool core::get_pool_transaction(const crypto::hash &id, transaction& tx) const
|
bool core::get_pool_transaction(const crypto::hash &id, transaction& tx) const
|
||||||
{
|
{
|
||||||
return m_mempool.get_transaction(id, tx);
|
return m_mempool.get_transaction(id, tx);
|
||||||
|
|
|
@ -396,6 +396,13 @@ namespace cryptonote
|
||||||
*/
|
*/
|
||||||
bool get_pool_transactions(std::list<transaction>& txs) const;
|
bool get_pool_transactions(std::list<transaction>& txs) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc tx_memory_pool::get_transactions
|
||||||
|
*
|
||||||
|
* @note see tx_memory_pool::get_transactions
|
||||||
|
*/
|
||||||
|
bool get_pool_transaction_hashes(std::vector<crypto::hash>& txs) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @copydoc tx_memory_pool::get_transaction
|
* @copydoc tx_memory_pool::get_transaction
|
||||||
*
|
*
|
||||||
|
|
|
@ -132,6 +132,9 @@ namespace cryptonote
|
||||||
//lock
|
//lock
|
||||||
tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
|
tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
|
||||||
tx.vin.push_back(in);
|
tx.vin.push_back(in);
|
||||||
|
|
||||||
|
tx.hash_valid = tx.blob_size_valid = false;
|
||||||
|
|
||||||
//LOG_PRINT("MINER_TX generated ok, block_reward=" << print_money(block_reward) << "(" << print_money(block_reward - fee) << "+" << print_money(fee)
|
//LOG_PRINT("MINER_TX generated ok, block_reward=" << print_money(block_reward) << "(" << print_money(block_reward - fee) << "+" << print_money(fee)
|
||||||
// << "), current_block_size=" << current_block_size << ", already_generated_coins=" << already_generated_coins << ", tx_id=" << get_transaction_hash(tx), LOG_LEVEL_2);
|
// << "), current_block_size=" << current_block_size << ", already_generated_coins=" << already_generated_coins << ", tx_id=" << get_transaction_hash(tx), LOG_LEVEL_2);
|
||||||
return true;
|
return true;
|
||||||
|
@ -451,6 +454,8 @@ namespace cryptonote
|
||||||
MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL);
|
MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tx.hash_valid = tx.blob_size_valid = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
@ -487,6 +492,7 @@ namespace cryptonote
|
||||||
bl.timestamp = 0;
|
bl.timestamp = 0;
|
||||||
bl.nonce = nonce;
|
bl.nonce = nonce;
|
||||||
miner::find_nonce_for_given_block(bl, 1, 0);
|
miner::find_nonce_for_given_block(bl, 1, 0);
|
||||||
|
bl.hash_valid = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
|
@ -423,6 +423,13 @@ namespace cryptonote
|
||||||
txs.push_back(tx_vt.second.tx);
|
txs.push_back(tx_vt.second.tx);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
void tx_memory_pool::get_transaction_hashes(std::vector<crypto::hash>& txs) const
|
||||||
|
{
|
||||||
|
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||||
|
for(const auto& tx_vt: m_transactions)
|
||||||
|
txs.push_back(get_transaction_hash(tx_vt.second.tx));
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------
|
||||||
//TODO: investigate whether boolean return is appropriate
|
//TODO: investigate whether boolean return is appropriate
|
||||||
bool tx_memory_pool::get_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos) const
|
bool tx_memory_pool::get_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos) const
|
||||||
{
|
{
|
||||||
|
@ -710,13 +717,22 @@ namespace cryptonote
|
||||||
size_t n_removed = 0;
|
size_t n_removed = 0;
|
||||||
size_t tx_size_limit = get_transaction_size_limit(version);
|
size_t tx_size_limit = get_transaction_size_limit(version);
|
||||||
for (auto it = m_transactions.begin(); it != m_transactions.end(); ) {
|
for (auto it = m_transactions.begin(); it != m_transactions.end(); ) {
|
||||||
|
bool remove = false;
|
||||||
|
const crypto::hash &txid = get_transaction_hash(it->second.tx);
|
||||||
if (it->second.blob_size >= tx_size_limit) {
|
if (it->second.blob_size >= tx_size_limit) {
|
||||||
LOG_PRINT_L1("Transaction " << get_transaction_hash(it->second.tx) << " is too big (" << it->second.blob_size << " bytes), removing it from pool");
|
LOG_PRINT_L1("Transaction " << txid << " is too big (" << it->second.blob_size << " bytes), removing it from pool");
|
||||||
|
remove = true;
|
||||||
|
}
|
||||||
|
else if (m_blockchain.have_tx(txid)) {
|
||||||
|
LOG_PRINT_L1("Transaction " << txid << " is in the blockchain, removing it from pool");
|
||||||
|
remove = true;
|
||||||
|
}
|
||||||
|
if (remove) {
|
||||||
remove_transaction_keyimages(it->second.tx);
|
remove_transaction_keyimages(it->second.tx);
|
||||||
auto sorted_it = find_tx_in_sorted_container(it->first);
|
auto sorted_it = find_tx_in_sorted_container(txid);
|
||||||
if (sorted_it == m_txs_by_fee_and_receive_time.end())
|
if (sorted_it == m_txs_by_fee_and_receive_time.end())
|
||||||
{
|
{
|
||||||
LOG_PRINT_L1("Removing tx " << it->first << " from tx pool, but it was not found in the sorted txs container!");
|
LOG_PRINT_L1("Removing tx " << txid << " from tx pool, but it was not found in the sorted txs container!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -233,6 +233,13 @@ namespace cryptonote
|
||||||
*/
|
*/
|
||||||
void get_transactions(std::list<transaction>& txs) const;
|
void get_transactions(std::list<transaction>& txs) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get a list of all transaction hashes in the pool
|
||||||
|
*
|
||||||
|
* @param txs return-by-reference the list of transactions
|
||||||
|
*/
|
||||||
|
void get_transaction_hashes(std::vector<crypto::hash>& txs) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get information about all transactions and key images in the pool
|
* @brief get information about all transactions and key images in the pool
|
||||||
*
|
*
|
||||||
|
|
|
@ -789,6 +789,14 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
bool core_rpc_server::on_get_transaction_pool_hashes(const COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::response& res)
|
||||||
|
{
|
||||||
|
CHECK_CORE_BUSY();
|
||||||
|
m_core.get_pool_transaction_hashes(res.tx_hashes);
|
||||||
|
res.status = CORE_RPC_STATUS_OK;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMMAND_RPC_STOP_DAEMON::response& res)
|
bool core_rpc_server::on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMMAND_RPC_STOP_DAEMON::response& res)
|
||||||
{
|
{
|
||||||
// FIXME: replace back to original m_p2p.send_stop_signal() after
|
// FIXME: replace back to original m_p2p.send_stop_signal() after
|
||||||
|
|
|
@ -92,6 +92,7 @@ namespace cryptonote
|
||||||
MAP_URI_AUTO_JON2_IF("/set_log_level", on_set_log_level, COMMAND_RPC_SET_LOG_LEVEL, !m_restricted)
|
MAP_URI_AUTO_JON2_IF("/set_log_level", on_set_log_level, COMMAND_RPC_SET_LOG_LEVEL, !m_restricted)
|
||||||
MAP_URI_AUTO_JON2_IF("/set_log_categories", on_set_log_categories, COMMAND_RPC_SET_LOG_CATEGORIES, !m_restricted)
|
MAP_URI_AUTO_JON2_IF("/set_log_categories", on_set_log_categories, COMMAND_RPC_SET_LOG_CATEGORIES, !m_restricted)
|
||||||
MAP_URI_AUTO_JON2("/get_transaction_pool", on_get_transaction_pool, COMMAND_RPC_GET_TRANSACTION_POOL)
|
MAP_URI_AUTO_JON2("/get_transaction_pool", on_get_transaction_pool, COMMAND_RPC_GET_TRANSACTION_POOL)
|
||||||
|
MAP_URI_AUTO_JON2("/get_transaction_pool_hashes.bin", on_get_transaction_pool_hashes, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES)
|
||||||
MAP_URI_AUTO_JON2_IF("/stop_daemon", on_stop_daemon, COMMAND_RPC_STOP_DAEMON, !m_restricted)
|
MAP_URI_AUTO_JON2_IF("/stop_daemon", on_stop_daemon, COMMAND_RPC_STOP_DAEMON, !m_restricted)
|
||||||
MAP_URI_AUTO_JON2("/getinfo", on_get_info, COMMAND_RPC_GET_INFO)
|
MAP_URI_AUTO_JON2("/getinfo", on_get_info, COMMAND_RPC_GET_INFO)
|
||||||
MAP_URI_AUTO_JON2_IF("/out_peers", on_out_peers, COMMAND_RPC_OUT_PEERS, !m_restricted)
|
MAP_URI_AUTO_JON2_IF("/out_peers", on_out_peers, COMMAND_RPC_OUT_PEERS, !m_restricted)
|
||||||
|
@ -145,6 +146,7 @@ namespace cryptonote
|
||||||
bool on_set_log_level(const COMMAND_RPC_SET_LOG_LEVEL::request& req, COMMAND_RPC_SET_LOG_LEVEL::response& res);
|
bool on_set_log_level(const COMMAND_RPC_SET_LOG_LEVEL::request& req, COMMAND_RPC_SET_LOG_LEVEL::response& res);
|
||||||
bool on_set_log_categories(const COMMAND_RPC_SET_LOG_CATEGORIES::request& req, COMMAND_RPC_SET_LOG_CATEGORIES::response& res);
|
bool on_set_log_categories(const COMMAND_RPC_SET_LOG_CATEGORIES::request& req, COMMAND_RPC_SET_LOG_CATEGORIES::response& res);
|
||||||
bool on_get_transaction_pool(const COMMAND_RPC_GET_TRANSACTION_POOL::request& req, COMMAND_RPC_GET_TRANSACTION_POOL::response& res);
|
bool on_get_transaction_pool(const COMMAND_RPC_GET_TRANSACTION_POOL::request& req, COMMAND_RPC_GET_TRANSACTION_POOL::response& res);
|
||||||
|
bool on_get_transaction_pool_hashes(const COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::response& res);
|
||||||
bool on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMMAND_RPC_STOP_DAEMON::response& res);
|
bool on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMMAND_RPC_STOP_DAEMON::response& res);
|
||||||
bool on_out_peers(const COMMAND_RPC_OUT_PEERS::request& req, COMMAND_RPC_OUT_PEERS::response& res);
|
bool on_out_peers(const COMMAND_RPC_OUT_PEERS::request& req, COMMAND_RPC_OUT_PEERS::response& res);
|
||||||
bool on_start_save_graph(const COMMAND_RPC_START_SAVE_GRAPH::request& req, COMMAND_RPC_START_SAVE_GRAPH::response& res);
|
bool on_start_save_graph(const COMMAND_RPC_START_SAVE_GRAPH::request& req, COMMAND_RPC_START_SAVE_GRAPH::response& res);
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace cryptonote
|
||||||
// advance which version they will stop working with
|
// advance which version they will stop working with
|
||||||
// Don't go over 32767 for any of these
|
// Don't go over 32767 for any of these
|
||||||
#define CORE_RPC_VERSION_MAJOR 1
|
#define CORE_RPC_VERSION_MAJOR 1
|
||||||
#define CORE_RPC_VERSION_MINOR 7
|
#define CORE_RPC_VERSION_MINOR 8
|
||||||
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
||||||
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
|
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
|
||||||
|
|
||||||
|
@ -1025,6 +1025,26 @@ namespace cryptonote
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct COMMAND_RPC_GET_TRANSACTION_POOL_HASHES
|
||||||
|
{
|
||||||
|
struct request
|
||||||
|
{
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct response
|
||||||
|
{
|
||||||
|
std::string status;
|
||||||
|
std::vector<crypto::hash> tx_hashes;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(status)
|
||||||
|
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(tx_hashes)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct COMMAND_RPC_GET_CONNECTIONS
|
struct COMMAND_RPC_GET_CONNECTIONS
|
||||||
{
|
{
|
||||||
struct request
|
struct request
|
||||||
|
|
|
@ -1384,13 +1384,13 @@ void wallet2::update_pool_state()
|
||||||
MDEBUG("update_pool_state start");
|
MDEBUG("update_pool_state start");
|
||||||
|
|
||||||
// get the pool state
|
// get the pool state
|
||||||
cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::request req;
|
cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::request req;
|
||||||
cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::response res;
|
cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::response res;
|
||||||
m_daemon_rpc_mutex.lock();
|
m_daemon_rpc_mutex.lock();
|
||||||
bool r = epee::net_utils::invoke_http_json("/get_transaction_pool", req, res, m_http_client, rpc_timeout);
|
bool r = epee::net_utils::invoke_http_json("/get_transaction_pool_hashes.bin", req, res, m_http_client, rpc_timeout);
|
||||||
m_daemon_rpc_mutex.unlock();
|
m_daemon_rpc_mutex.unlock();
|
||||||
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_transaction_pool");
|
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_transaction_pool_hashes.bin");
|
||||||
THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_transaction_pool");
|
THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_transaction_pool_hashes.bin");
|
||||||
THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::get_tx_pool_error);
|
THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::get_tx_pool_error);
|
||||||
MDEBUG("update_pool_state got pool");
|
MDEBUG("update_pool_state got pool");
|
||||||
|
|
||||||
|
@ -1398,11 +1398,11 @@ void wallet2::update_pool_state()
|
||||||
std::unordered_map<crypto::hash, wallet2::unconfirmed_transfer_details>::iterator it = m_unconfirmed_txs.begin();
|
std::unordered_map<crypto::hash, wallet2::unconfirmed_transfer_details>::iterator it = m_unconfirmed_txs.begin();
|
||||||
while (it != m_unconfirmed_txs.end())
|
while (it != m_unconfirmed_txs.end())
|
||||||
{
|
{
|
||||||
const std::string txid = epee::string_tools::pod_to_hex(it->first);
|
const crypto::hash &txid = it->first;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto it2: res.transactions)
|
for (const auto &it2: res.tx_hashes)
|
||||||
{
|
{
|
||||||
if (it2.id_hash == txid)
|
if (it2 == txid)
|
||||||
{
|
{
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1453,11 +1453,11 @@ void wallet2::update_pool_state()
|
||||||
std::unordered_map<crypto::hash, wallet2::payment_details>::iterator uit = m_unconfirmed_payments.begin();
|
std::unordered_map<crypto::hash, wallet2::payment_details>::iterator uit = m_unconfirmed_payments.begin();
|
||||||
while (uit != m_unconfirmed_payments.end())
|
while (uit != m_unconfirmed_payments.end())
|
||||||
{
|
{
|
||||||
const std::string txid = string_tools::pod_to_hex(uit->first);
|
const crypto::hash &txid = uit->first;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto it2: res.transactions)
|
for (const auto &it2: res.tx_hashes)
|
||||||
{
|
{
|
||||||
if (it2.id_hash == txid)
|
if (it2 == txid)
|
||||||
{
|
{
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1466,18 +1466,16 @@ void wallet2::update_pool_state()
|
||||||
auto pit = uit++;
|
auto pit = uit++;
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
|
MDEBUG("Removing " << txid << " from unconfirmed payments, not found in pool");
|
||||||
m_unconfirmed_payments.erase(pit);
|
m_unconfirmed_payments.erase(pit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MDEBUG("update_pool_state done second loop");
|
MDEBUG("update_pool_state done second loop");
|
||||||
|
|
||||||
// add new pool txes to us
|
// gather txids of new pool txes to us
|
||||||
for (auto it: res.transactions)
|
std::vector<crypto::hash> txids;
|
||||||
|
for (const auto &txid: res.tx_hashes)
|
||||||
{
|
{
|
||||||
cryptonote::blobdata txid_data;
|
|
||||||
if(epee::string_tools::parse_hexstr_to_binbuff(it.id_hash, txid_data) && txid_data.size() == sizeof(crypto::hash))
|
|
||||||
{
|
|
||||||
const crypto::hash txid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
|
|
||||||
if (m_scanned_pool_txs[0].find(txid) != m_scanned_pool_txs[0].end() || m_scanned_pool_txs[1].find(txid) != m_scanned_pool_txs[1].end())
|
if (m_scanned_pool_txs[0].find(txid) != m_scanned_pool_txs[0].end() || m_scanned_pool_txs[1].find(txid) != m_scanned_pool_txs[1].end())
|
||||||
{
|
{
|
||||||
LOG_PRINT_L2("Already seen " << txid << ", skipped");
|
LOG_PRINT_L2("Already seen " << txid << ", skipped");
|
||||||
|
@ -1498,26 +1496,46 @@ void wallet2::update_pool_state()
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
// not one of those we sent ourselves
|
// not one of those we sent ourselves
|
||||||
|
txids.push_back(txid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_PRINT_L1("We sent that one");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_PRINT_L1("Already saw that one, it's for us");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get those txes
|
||||||
|
if (!txids.empty())
|
||||||
|
{
|
||||||
cryptonote::COMMAND_RPC_GET_TRANSACTIONS::request req;
|
cryptonote::COMMAND_RPC_GET_TRANSACTIONS::request req;
|
||||||
cryptonote::COMMAND_RPC_GET_TRANSACTIONS::response res;
|
cryptonote::COMMAND_RPC_GET_TRANSACTIONS::response res;
|
||||||
req.txs_hashes.push_back(it.id_hash);
|
for (const auto &txid: txids)
|
||||||
MDEBUG("asking for " << it.id_hash);
|
req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
|
||||||
|
MDEBUG("asking for " << txids.size() << " transactions");
|
||||||
req.decode_as_json = false;
|
req.decode_as_json = false;
|
||||||
m_daemon_rpc_mutex.lock();
|
m_daemon_rpc_mutex.lock();
|
||||||
bool r = epee::net_utils::invoke_http_json("/gettransactions", req, res, m_http_client, rpc_timeout);
|
bool r = epee::net_utils::invoke_http_json("/gettransactions", req, res, m_http_client, rpc_timeout);
|
||||||
MDEBUG("asked for " << it.id_hash << ", got " << r << " and " << res.status);
|
|
||||||
m_daemon_rpc_mutex.unlock();
|
m_daemon_rpc_mutex.unlock();
|
||||||
|
MDEBUG("Got " << r << " and " << res.status);
|
||||||
if (r && res.status == CORE_RPC_STATUS_OK)
|
if (r && res.status == CORE_RPC_STATUS_OK)
|
||||||
{
|
{
|
||||||
if (res.txs.size() == 1)
|
if (res.txs.size() == txids.size())
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
for (const auto &txid: txids)
|
||||||
{
|
{
|
||||||
// might have just been put in a block
|
// might have just been put in a block
|
||||||
if (res.txs[0].in_pool)
|
if (res.txs[n].in_pool)
|
||||||
{
|
{
|
||||||
cryptonote::transaction tx;
|
cryptonote::transaction tx;
|
||||||
cryptonote::blobdata bd;
|
cryptonote::blobdata bd;
|
||||||
crypto::hash tx_hash, tx_prefix_hash;
|
crypto::hash tx_hash, tx_prefix_hash;
|
||||||
if (epee::string_tools::parse_hexstr_to_binbuff(res.txs[0].as_hex, bd))
|
if (epee::string_tools::parse_hexstr_to_binbuff(res.txs[n].as_hex, bd))
|
||||||
{
|
{
|
||||||
if (cryptonote::parse_and_validate_tx_from_blob(bd, tx, tx_hash, tx_prefix_hash))
|
if (cryptonote::parse_and_validate_tx_from_blob(bd, tx, tx_hash, tx_prefix_hash))
|
||||||
{
|
{
|
||||||
|
@ -1550,10 +1568,12 @@ void wallet2::update_pool_state()
|
||||||
{
|
{
|
||||||
LOG_PRINT_L1("Tx " << txid << " was in pool, but is no more");
|
LOG_PRINT_L1("Tx " << txid << " was in pool, but is no more");
|
||||||
}
|
}
|
||||||
|
++n;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_PRINT_L0("Expected 1 tx, got " << res.txs.size());
|
LOG_PRINT_L0("Expected " << txids.size() << " tx(es), got " << res.txs.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1561,21 +1581,6 @@ void wallet2::update_pool_state()
|
||||||
LOG_PRINT_L0("Error calling gettransactions daemon RPC: r " << r << ", status " << res.status);
|
LOG_PRINT_L0("Error calling gettransactions daemon RPC: r " << r << ", status " << res.status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_PRINT_L1("We sent that one");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_PRINT_L1("Already saw that one, it's for us");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_PRINT_L0("Failed to parse txid");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MDEBUG("update_pool_state end");
|
MDEBUG("update_pool_state end");
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -331,6 +331,7 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
|
||||||
|
|
||||||
// Miner tx with empty signatures 2nd vector
|
// Miner tx with empty signatures 2nd vector
|
||||||
tx.signatures.resize(1);
|
tx.signatures.resize(1);
|
||||||
|
tx.invalidate_hashes();
|
||||||
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
||||||
ASSERT_EQ(7, blob.size()); // 5 bytes + 2 bytes vin[0] + 0 bytes extra + 0 bytes signatures
|
ASSERT_EQ(7, blob.size()); // 5 bytes + 2 bytes vin[0] + 0 bytes extra + 0 bytes signatures
|
||||||
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
|
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
|
||||||
|
@ -345,16 +346,19 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
|
||||||
tx.signatures.resize(2);
|
tx.signatures.resize(2);
|
||||||
tx.signatures[0].resize(0);
|
tx.signatures[0].resize(0);
|
||||||
tx.signatures[1].resize(0);
|
tx.signatures[1].resize(0);
|
||||||
|
tx.invalidate_hashes();
|
||||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||||
|
|
||||||
// Miner tx with 2 signatures
|
// Miner tx with 2 signatures
|
||||||
tx.signatures[0].resize(1);
|
tx.signatures[0].resize(1);
|
||||||
tx.signatures[1].resize(1);
|
tx.signatures[1].resize(1);
|
||||||
|
tx.invalidate_hashes();
|
||||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||||
|
|
||||||
// Two txin_gen, no signatures
|
// Two txin_gen, no signatures
|
||||||
tx.vin.push_back(txin_gen1);
|
tx.vin.push_back(txin_gen1);
|
||||||
tx.signatures.resize(0);
|
tx.signatures.resize(0);
|
||||||
|
tx.invalidate_hashes();
|
||||||
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
||||||
ASSERT_EQ(9, blob.size()); // 5 bytes + 2 * 2 bytes vins + 0 bytes extra + 0 bytes signatures
|
ASSERT_EQ(9, blob.size()); // 5 bytes + 2 * 2 bytes vins + 0 bytes extra + 0 bytes signatures
|
||||||
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
|
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
|
||||||
|
@ -363,10 +367,12 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
|
||||||
|
|
||||||
// Two txin_gen, signatures vector contains only one empty element
|
// Two txin_gen, signatures vector contains only one empty element
|
||||||
tx.signatures.resize(1);
|
tx.signatures.resize(1);
|
||||||
|
tx.invalidate_hashes();
|
||||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||||
|
|
||||||
// Two txin_gen, signatures vector contains two empty elements
|
// Two txin_gen, signatures vector contains two empty elements
|
||||||
tx.signatures.resize(2);
|
tx.signatures.resize(2);
|
||||||
|
tx.invalidate_hashes();
|
||||||
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
||||||
ASSERT_EQ(9, blob.size()); // 5 bytes + 2 * 2 bytes vins + 0 bytes extra + 0 bytes signatures
|
ASSERT_EQ(9, blob.size()); // 5 bytes + 2 * 2 bytes vins + 0 bytes extra + 0 bytes signatures
|
||||||
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
|
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
|
||||||
|
@ -375,18 +381,21 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
|
||||||
|
|
||||||
// Two txin_gen, signatures vector contains three empty elements
|
// Two txin_gen, signatures vector contains three empty elements
|
||||||
tx.signatures.resize(3);
|
tx.signatures.resize(3);
|
||||||
|
tx.invalidate_hashes();
|
||||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||||
|
|
||||||
// Two txin_gen, signatures vector contains two non empty elements
|
// Two txin_gen, signatures vector contains two non empty elements
|
||||||
tx.signatures.resize(2);
|
tx.signatures.resize(2);
|
||||||
tx.signatures[0].resize(1);
|
tx.signatures[0].resize(1);
|
||||||
tx.signatures[1].resize(1);
|
tx.signatures[1].resize(1);
|
||||||
|
tx.invalidate_hashes();
|
||||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||||
|
|
||||||
// A few bytes instead of signature
|
// A few bytes instead of signature
|
||||||
tx.vin.clear();
|
tx.vin.clear();
|
||||||
tx.vin.push_back(txin_gen1);
|
tx.vin.push_back(txin_gen1);
|
||||||
tx.signatures.clear();
|
tx.signatures.clear();
|
||||||
|
tx.invalidate_hashes();
|
||||||
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
||||||
blob.append(std::string(sizeof(crypto::signature) / 2, 'x'));
|
blob.append(std::string(sizeof(crypto::signature) / 2, 'x'));
|
||||||
ASSERT_FALSE(serialization::parse_binary(blob, tx1));
|
ASSERT_FALSE(serialization::parse_binary(blob, tx1));
|
||||||
|
@ -406,6 +415,7 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
|
||||||
tx.vin.push_back(txin_to_key1);
|
tx.vin.push_back(txin_to_key1);
|
||||||
tx.signatures.resize(1);
|
tx.signatures.resize(1);
|
||||||
tx.signatures[0].resize(2);
|
tx.signatures[0].resize(2);
|
||||||
|
tx.invalidate_hashes();
|
||||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||||
|
|
||||||
// Too much signatures for two inputs
|
// Too much signatures for two inputs
|
||||||
|
@ -413,24 +423,28 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
|
||||||
tx.signatures[0].resize(2);
|
tx.signatures[0].resize(2);
|
||||||
tx.signatures[1].resize(2);
|
tx.signatures[1].resize(2);
|
||||||
tx.signatures[2].resize(2);
|
tx.signatures[2].resize(2);
|
||||||
|
tx.invalidate_hashes();
|
||||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||||
|
|
||||||
// First signatures vector contains too little elements
|
// First signatures vector contains too little elements
|
||||||
tx.signatures.resize(2);
|
tx.signatures.resize(2);
|
||||||
tx.signatures[0].resize(1);
|
tx.signatures[0].resize(1);
|
||||||
tx.signatures[1].resize(2);
|
tx.signatures[1].resize(2);
|
||||||
|
tx.invalidate_hashes();
|
||||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||||
|
|
||||||
// First signatures vector contains too much elements
|
// First signatures vector contains too much elements
|
||||||
tx.signatures.resize(2);
|
tx.signatures.resize(2);
|
||||||
tx.signatures[0].resize(3);
|
tx.signatures[0].resize(3);
|
||||||
tx.signatures[1].resize(2);
|
tx.signatures[1].resize(2);
|
||||||
|
tx.invalidate_hashes();
|
||||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||||
|
|
||||||
// There are signatures for each input
|
// There are signatures for each input
|
||||||
tx.signatures.resize(2);
|
tx.signatures.resize(2);
|
||||||
tx.signatures[0].resize(2);
|
tx.signatures[0].resize(2);
|
||||||
tx.signatures[1].resize(2);
|
tx.signatures[1].resize(2);
|
||||||
|
tx.invalidate_hashes();
|
||||||
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
||||||
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
|
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
|
||||||
ASSERT_EQ(tx, tx1);
|
ASSERT_EQ(tx, tx1);
|
||||||
|
|
Loading…
Reference in New Issue