Merge pull request #20 from warptangent/fix_transfers
Fix transfers Output indexing was being handled improperly. These changes fix that. Wallets (re-)created using this branch will need to be (re-)re-created in order to get correct output indices.
This commit is contained in:
commit
030eab7a49
|
@ -477,7 +477,44 @@ tx_out BlockchainLMDB::output_from_blob(const blobdata& blob) const
|
||||||
uint64_t BlockchainLMDB::get_output_global_index(const uint64_t& amount, const uint64_t& index) const
|
uint64_t BlockchainLMDB::get_output_global_index(const uint64_t& amount, const uint64_t& index) const
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||||
return 0;
|
check_open();
|
||||||
|
|
||||||
|
txn_safe txn;
|
||||||
|
if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn))
|
||||||
|
throw0(DB_ERROR("Failed to create a transaction for the db"));
|
||||||
|
|
||||||
|
lmdb_cur cur(txn, m_output_amounts);
|
||||||
|
|
||||||
|
MDB_val_copy<uint64_t> k(amount);
|
||||||
|
MDB_val v;
|
||||||
|
|
||||||
|
auto result = mdb_cursor_get(cur, &k, &v, MDB_SET);
|
||||||
|
if (result == MDB_NOTFOUND)
|
||||||
|
throw1(OUTPUT_DNE("Attempting to get an output index by amount and amount index, but amount not found"));
|
||||||
|
else if (result)
|
||||||
|
throw0(DB_ERROR("DB error attempting to get an output"));
|
||||||
|
|
||||||
|
size_t num_elems = 0;
|
||||||
|
mdb_cursor_count(cur, &num_elems);
|
||||||
|
if (num_elems <= index)
|
||||||
|
throw1(OUTPUT_DNE("Attempting to get an output index by amount and amount index, but output not found"));
|
||||||
|
|
||||||
|
mdb_cursor_get(cur, &k, &v, MDB_FIRST_DUP);
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < index; ++i)
|
||||||
|
{
|
||||||
|
mdb_cursor_get(cur, &k, &v, MDB_NEXT_DUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
mdb_cursor_get(cur, &k, &v, MDB_GET_CURRENT);
|
||||||
|
|
||||||
|
uint64_t glob_index = *(const uint64_t*)v.mv_data;
|
||||||
|
|
||||||
|
cur.close();
|
||||||
|
|
||||||
|
txn.commit();
|
||||||
|
|
||||||
|
return glob_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockchainLMDB::check_open() const
|
void BlockchainLMDB::check_open() const
|
||||||
|
@ -1123,11 +1160,13 @@ crypto::public_key BlockchainLMDB::get_output_key(const uint64_t& amount, const
|
||||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||||
check_open();
|
check_open();
|
||||||
|
|
||||||
|
uint64_t glob_index = get_output_global_index(amount, index);
|
||||||
|
|
||||||
txn_safe txn;
|
txn_safe txn;
|
||||||
if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn))
|
if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn))
|
||||||
throw0(DB_ERROR("Failed to create a transaction for the db"));
|
throw0(DB_ERROR("Failed to create a transaction for the db"));
|
||||||
|
|
||||||
MDB_val_copy<uint64_t> k(get_output_global_index(amount, index));
|
MDB_val_copy<uint64_t> k(glob_index);
|
||||||
MDB_val v;
|
MDB_val v;
|
||||||
auto get_result = mdb_get(txn, m_output_keys, &k, &v);
|
auto get_result = mdb_get(txn, m_output_keys, &k, &v);
|
||||||
if (get_result == MDB_NOTFOUND)
|
if (get_result == MDB_NOTFOUND)
|
||||||
|
@ -1317,6 +1356,85 @@ std::vector<uint64_t> BlockchainLMDB::get_tx_output_indices(const crypto::hash&
|
||||||
return index_vec;
|
return index_vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<uint64_t> BlockchainLMDB::get_tx_amount_output_indices(const crypto::hash& h) const
|
||||||
|
{
|
||||||
|
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||||
|
check_open();
|
||||||
|
std::vector<uint64_t> index_vec;
|
||||||
|
std::vector<uint64_t> index_vec2;
|
||||||
|
|
||||||
|
// get the transaction's global output indices first
|
||||||
|
index_vec = get_tx_output_indices(h);
|
||||||
|
// these are next used to obtain the amount output indices
|
||||||
|
|
||||||
|
transaction tx = get_tx(h);
|
||||||
|
|
||||||
|
txn_safe txn;
|
||||||
|
if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn))
|
||||||
|
throw0(DB_ERROR("Failed to create a transaction for the db"));
|
||||||
|
|
||||||
|
uint64_t i = 0;
|
||||||
|
uint64_t global_index;
|
||||||
|
BOOST_FOREACH(const auto& vout, tx.vout)
|
||||||
|
{
|
||||||
|
uint64_t amount = vout.amount;
|
||||||
|
|
||||||
|
global_index = index_vec[i];
|
||||||
|
|
||||||
|
lmdb_cur cur(txn, m_output_amounts);
|
||||||
|
|
||||||
|
MDB_val_copy<uint64_t> k(amount);
|
||||||
|
MDB_val v;
|
||||||
|
|
||||||
|
auto result = mdb_cursor_get(cur, &k, &v, MDB_SET);
|
||||||
|
if (result == MDB_NOTFOUND)
|
||||||
|
throw1(OUTPUT_DNE("Attempting to get an output index by amount and amount index, but amount not found"));
|
||||||
|
else if (result)
|
||||||
|
throw0(DB_ERROR("DB error attempting to get an output"));
|
||||||
|
|
||||||
|
size_t num_elems = 0;
|
||||||
|
mdb_cursor_count(cur, &num_elems);
|
||||||
|
|
||||||
|
mdb_cursor_get(cur, &k, &v, MDB_FIRST_DUP);
|
||||||
|
|
||||||
|
uint64_t amount_output_index = 0;
|
||||||
|
uint64_t output_index = 0;
|
||||||
|
bool found_index = false;
|
||||||
|
for (uint64_t j = 0; j < num_elems; ++j)
|
||||||
|
{
|
||||||
|
mdb_cursor_get(cur, &k, &v, MDB_GET_CURRENT);
|
||||||
|
output_index = *(const uint64_t *)v.mv_data;
|
||||||
|
if (output_index == global_index)
|
||||||
|
{
|
||||||
|
amount_output_index = j;
|
||||||
|
found_index = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mdb_cursor_get(cur, &k, &v, MDB_NEXT_DUP);
|
||||||
|
}
|
||||||
|
if (found_index)
|
||||||
|
{
|
||||||
|
index_vec2.push_back(amount_output_index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// not found
|
||||||
|
cur.close();
|
||||||
|
txn.commit();
|
||||||
|
throw1(OUTPUT_DNE("specified output not found in db"));
|
||||||
|
}
|
||||||
|
|
||||||
|
cur.close();
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
txn.commit();
|
||||||
|
|
||||||
|
return index_vec2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool BlockchainLMDB::has_key_image(const crypto::key_image& img) const
|
bool BlockchainLMDB::has_key_image(const crypto::key_image& img) const
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||||
|
|
|
@ -166,6 +166,7 @@ public:
|
||||||
virtual tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) const;
|
virtual tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) const;
|
||||||
|
|
||||||
virtual std::vector<uint64_t> get_tx_output_indices(const crypto::hash& h) const;
|
virtual std::vector<uint64_t> get_tx_output_indices(const crypto::hash& h) const;
|
||||||
|
virtual std::vector<uint64_t> get_tx_amount_output_indices(const crypto::hash& h) const;
|
||||||
|
|
||||||
virtual bool has_key_image(const crypto::key_image& img) const;
|
virtual bool has_key_image(const crypto::key_image& img) const;
|
||||||
|
|
||||||
|
|
|
@ -1789,7 +1789,8 @@ bool Blockchain::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<u
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
indexs = m_db->get_tx_output_indices(tx_id);
|
// get amount output indexes, currently referred to in parts as "output global indices", but they are actually specific to amounts
|
||||||
|
indexs = m_db->get_tx_amount_output_indices(tx_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
@ -1848,7 +1849,7 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_bloc
|
||||||
// signature spending it.
|
// signature spending it.
|
||||||
if(!check_tx_input(in_to_key, tx_prefix_hash, tx.signatures[sig_index], pmax_used_block_height))
|
if(!check_tx_input(in_to_key, tx_prefix_hash, tx.signatures[sig_index], pmax_used_block_height))
|
||||||
{
|
{
|
||||||
LOG_PRINT_L0("Failed to check ring signature for tx " << get_transaction_hash(tx));
|
LOG_PRINT_L0("Failed to check ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index << " *pmax_used_block_height: " << *pmax_used_block_height);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -452,6 +452,9 @@ public:
|
||||||
// return a vector of indices corresponding to the global output index for
|
// return a vector of indices corresponding to the global output index for
|
||||||
// each output in the transaction with hash <h>
|
// each output in the transaction with hash <h>
|
||||||
virtual std::vector<uint64_t> get_tx_output_indices(const crypto::hash& h) const = 0;
|
virtual std::vector<uint64_t> get_tx_output_indices(const crypto::hash& h) const = 0;
|
||||||
|
// return a vector of indices corresponding to the amount output index for
|
||||||
|
// each output in the transaction with hash <h>
|
||||||
|
virtual std::vector<uint64_t> get_tx_amount_output_indices(const crypto::hash& h) const = 0;
|
||||||
|
|
||||||
// returns true if key image <img> is present in spent key images storage
|
// returns true if key image <img> is present in spent key images storage
|
||||||
virtual bool has_key_image(const crypto::key_image& img) const = 0;
|
virtual bool has_key_image(const crypto::key_image& img) const = 0;
|
||||||
|
|
Loading…
Reference in New Issue