diff options
author | Thomas Winget <tewinget@gmail.com> | 2015-01-09 20:04:47 -0500 |
---|---|---|
committer | Thomas Winget <tewinget@gmail.com> | 2015-01-09 20:04:47 -0500 |
commit | 030eab7a49ee3846e7591edd81cf56737c850ef3 (patch) | |
tree | 53facbb62b157f403cfadbd31832a28b734f04c8 /src/cryptonote_core/BlockchainDB_impl | |
parent | throw inline functions need to keep exception type (diff) | |
parent | Fix transfers to support mixins (diff) | |
download | monero-030eab7a49ee3846e7591edd81cf56737c850ef3.tar.xz |
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.
Diffstat (limited to 'src/cryptonote_core/BlockchainDB_impl')
-rw-r--r-- | src/cryptonote_core/BlockchainDB_impl/db_lmdb.cpp | 122 | ||||
-rw-r--r-- | src/cryptonote_core/BlockchainDB_impl/db_lmdb.h | 1 |
2 files changed, 121 insertions, 2 deletions
diff --git a/src/cryptonote_core/BlockchainDB_impl/db_lmdb.cpp b/src/cryptonote_core/BlockchainDB_impl/db_lmdb.cpp index 0184dbc58..835b9248f 100644 --- a/src/cryptonote_core/BlockchainDB_impl/db_lmdb.cpp +++ b/src/cryptonote_core/BlockchainDB_impl/db_lmdb.cpp @@ -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 { 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 @@ -1123,11 +1160,13 @@ crypto::public_key BlockchainLMDB::get_output_key(const uint64_t& amount, const LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); + uint64_t glob_index = get_output_global_index(amount, index); + txn_safe txn; if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) 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; auto get_result = mdb_get(txn, m_output_keys, &k, &v); if (get_result == MDB_NOTFOUND) @@ -1317,6 +1356,85 @@ std::vector<uint64_t> BlockchainLMDB::get_tx_output_indices(const crypto::hash& 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 { LOG_PRINT_L3("BlockchainLMDB::" << __func__); diff --git a/src/cryptonote_core/BlockchainDB_impl/db_lmdb.h b/src/cryptonote_core/BlockchainDB_impl/db_lmdb.h index 6696ef492..d95d19019 100644 --- a/src/cryptonote_core/BlockchainDB_impl/db_lmdb.h +++ b/src/cryptonote_core/BlockchainDB_impl/db_lmdb.h @@ -166,6 +166,7 @@ public: 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_amount_output_indices(const crypto::hash& h) const; virtual bool has_key_image(const crypto::key_image& img) const; |