Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' v 3.3.3
Browse files Browse the repository at this point in the history
  • Loading branch information
homdx committed Dec 3, 2018
2 parents 700abee + fa8fa01 commit 7aa7714
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 60 deletions.
4 changes: 4 additions & 0 deletions ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## Release Notes

### v3.3.3

- Fixed bug when `walletd` fails to create transactions for certain coins.

### v3.3.2

- Fixed bug when an invalid transaction may persist in the payment queue.
Expand Down
56 changes: 31 additions & 25 deletions src/Core/BlockChainState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1083,24 +1083,6 @@ std::vector<api::Output> BlockChainState::get_random_outputs(
std::vector<api::Output> result;
uint32_t total_count = next_global_index_for_amount(amount);
// We might need better algorithm if we have lots of locked amounts
if (total_count <= output_count) {
for (uint32_t i = 0; i != total_count; ++i) {
api::Output item;
UnlockTimePublickKeyHeightSpent unp;
item.amount = amount;
item.index = i;
invariant(read_amount_output(amount, i, &unp), "global amount < total_count not found");
item.unlock_block_or_timestamp = unp.unlock_block_or_timestamp;
item.public_key = unp.public_key;
item.height = unp.height;
if (unp.spent || unp.height > confirmed_height)
continue;
if (!m_currency.is_transaction_spend_time_unlocked(item.unlock_block_or_timestamp, confirmed_height, time))
continue;
result.push_back(item);
}
return result;
}
std::set<uint32_t> tried_or_added;
crypto::random_engine<uint64_t> generator;
std::lognormal_distribution<double> distribution(1.9, 1.0); // Magic params here
Expand All @@ -1122,14 +1104,8 @@ std::vector<api::Output> BlockChainState::get_random_outputs(
}
if (!tried_or_added.insert(num).second)
continue;
api::Output item;
UnlockTimePublickKeyHeightSpent unp;
item.amount = amount;
item.index = num;
invariant(read_amount_output(amount, num, &unp), "num < total_count not found");
item.unlock_block_or_timestamp = unp.unlock_block_or_timestamp;
item.public_key = unp.public_key;
item.height = unp.height;
if (unp.height > confirmed_height) {
if (confirmed_height + 128 < get_tip_height())
total_count = num;
Expand All @@ -1140,10 +1116,40 @@ std::vector<api::Output> BlockChainState::get_random_outputs(
}
if (unp.spent)
continue;
if (!m_currency.is_transaction_spend_time_unlocked(item.unlock_block_or_timestamp, confirmed_height, time))
if (!m_currency.is_transaction_spend_time_unlocked(unp.unlock_block_or_timestamp, confirmed_height, time))
continue;
api::Output item;
item.amount = amount;
item.index = num;
item.unlock_block_or_timestamp = unp.unlock_block_or_timestamp;
item.public_key = unp.public_key;
item.height = unp.height;
result.push_back(item);
}
if(result.size() < output_count){
// Read the whole index.
size_t attempts = 0;
for (DB::Cursor cur = m_db.rbegin(AMOUNT_OUTPUT_PREFIX + common::write_varint_sqlite4(amount)); result.size() < output_count && attempts < 10000 && !cur.end(); cur.next(), ++attempts) { // TODO - 10000
const char *be = cur.get_suffix().data();
const char *en = be + cur.get_suffix().size();
uint32_t global_index = common::integer_cast<uint32_t>(common::read_varint_sqlite4(be, en));
if (tried_or_added.count(global_index) != 0)
continue;
UnlockTimePublickKeyHeightSpent unp;
seria::from_binary(unp, cur.get_value_array());
if (unp.spent || unp.height > confirmed_height)
continue;
if (!m_currency.is_transaction_spend_time_unlocked(unp.unlock_block_or_timestamp, confirmed_height, time))
continue;
api::Output item;
item.amount = amount;
item.index = global_index;
item.unlock_block_or_timestamp = unp.unlock_block_or_timestamp;
item.public_key = unp.public_key;
item.height = unp.height;
result.push_back(item);
}
}
return result;
}

Expand Down
42 changes: 22 additions & 20 deletions src/Core/TransactionBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,28 +177,30 @@ void UnspentSelector::add_mixed_inputs(const SecretKey &view_secret_key, const W
api::bytecoind::GetRandomOutputs::Response &&ra_response) {
for (const auto &uu : m_used_unspents) {
std::vector<api::Output> mix_outputs;
auto &our_ra_outputs = ra_response.outputs[uu.amount];
while (mix_outputs.size() < anonymity + 1) {
if (our_ra_outputs.empty())
throw json_rpc::Error(api::walletd::CreateTransaction::NOT_ENOUGH_ANONYMITY,
"Requested anonymity too high for amount " + common::to_string(uu.amount));
mix_outputs.push_back(std::move(our_ra_outputs.back()));
our_ra_outputs.pop_back();
}
std::sort(mix_outputs.begin(), mix_outputs.end(), APIOutputLessGlobalIndex);
mix_outputs.erase(
std::unique(mix_outputs.begin(), mix_outputs.end(), APIOutputEqualGlobalIndex), mix_outputs.end());
int best_distance = 0;
size_t best_index = mix_outputs.size();
for (size_t i = 0; i != mix_outputs.size(); ++i) {
int distance = abs(int(uu.index) - int(mix_outputs[i].index));
if (best_index == mix_outputs.size() || distance < best_distance) {
best_index = i;
best_distance = distance;
if(anonymity != 0){
auto &our_ra_outputs = ra_response.outputs[uu.amount];
while (mix_outputs.size() < anonymity + 1) {
if (our_ra_outputs.empty())
throw json_rpc::Error(api::walletd::CreateTransaction::NOT_ENOUGH_ANONYMITY,
"Requested anonymity too high for amount " + common::to_string(uu.amount));
mix_outputs.push_back(std::move(our_ra_outputs.back()));
our_ra_outputs.pop_back();
}
std::sort(mix_outputs.begin(), mix_outputs.end(), APIOutputLessGlobalIndex);
mix_outputs.erase(
std::unique(mix_outputs.begin(), mix_outputs.end(), APIOutputEqualGlobalIndex), mix_outputs.end());
int best_distance = 0;
size_t best_index = mix_outputs.size();
for (size_t i = 0; i != mix_outputs.size(); ++i) {
int distance = abs(int(uu.index) - int(mix_outputs[i].index));
if (best_index == mix_outputs.size() || distance < best_distance) {
best_index = i;
best_distance = distance;
}
}
invariant(best_index != mix_outputs.size(), "");
mix_outputs.erase(mix_outputs.begin() + best_index);
}
invariant(best_index != mix_outputs.size(), "");
mix_outputs.erase(mix_outputs.begin() + best_index);
AccountKeys sender_keys;
sender_keys.view_secret_key = view_secret_key;
if (!m_currency.parse_account_address_string(uu.address, &sender_keys.address))
Expand Down
23 changes: 10 additions & 13 deletions src/Core/WalletNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,30 +461,28 @@ bool WalletNode::handle_create_transaction(http::Client *who, http::RequestData
request.transaction.anonymity + 1; // Ask excess output for the case of collision with our output
ra_request.amounts = selector.get_ra_amounts();
api::bytecoind::GetRandomOutputs::Response ra_response;
if (m_inproc_node) {
m_inproc_node->on_get_random_outputs(
nullptr, http::RequestData(raw_request), json_rpc::Request(), std::move(ra_request), ra_response);
if (m_inproc_node || request.transaction.anonymity == 0) {
if(request.transaction.anonymity != 0)
m_inproc_node->on_get_random_outputs(
nullptr, http::RequestData(raw_request), json_rpc::Request(), std::move(ra_request), ra_response);
selector.add_mixed_inputs(m_wallet_state.get_wallet().get_view_secret_key(),
request.any_spend_address ? &m_wallet_state.get_wallet() : nullptr, only_records, &builder,
request.transaction.anonymity, std::move(ra_response));
Transaction tx = builder.sign(m_wallet_state.get_wallet().get_tx_derivation_seed());
response.binary_transaction = seria::to_binary(tx);
Hash transaction_hash = get_transaction_hash(tx);
if (request.save_history && !m_wallet_state.get_wallet().save_history(transaction_hash, history)) {
const Hash tx_hash = get_transaction_hash(tx);
if (request.save_history && !m_wallet_state.get_wallet().save_history(tx_hash, history)) {
m_log(logging::ERROR)
<< "Saving transaction history failed, you will need to pass list of destination addresses to generate sending proof for tx="
<< transaction_hash << std::endl;
<< tx_hash << std::endl;
response.save_history_error = true;
}

api::Transaction ptx{};
if (!m_wallet_state.parse_raw_transaction(ptx, tx, transaction_hash)) {
// TODO - process error
}
if (!m_wallet_state.parse_raw_transaction(ptx, tx, tx_hash))
throw json_rpc::Error(json_rpc::INTERNAL_ERROR, "Created trsnsaction cannot be parsed");
response.transaction = ptx;
return true;
}

api::walletd::CreateTransaction::Request request_copy = request; // TODO ???
http::RequestData new_request =
json_rpc::create_request(api::bytecoind::url(), api::bytecoind::GetRandomOutputs::method(), ra_request);
Expand All @@ -499,7 +497,6 @@ bool WalletNode::handle_create_transaction(http::Client *who, http::RequestData
}
Transaction tx{};
api::walletd::CreateTransaction::Response last_response;
Hash tx_hash{};
json_rpc::Response json_resp(random_response.body);
api::bytecoind::GetRandomOutputs::Response ra_response;
json_resp.get_result(ra_response);
Expand All @@ -508,7 +505,7 @@ bool WalletNode::handle_create_transaction(http::Client *who, http::RequestData
request.transaction.anonymity, std::move(ra_response));
tx = builder.sign(m_wallet_state.get_wallet().get_tx_derivation_seed());
last_response.binary_transaction = seria::to_binary(tx);
tx_hash = get_transaction_hash(tx);
const Hash tx_hash = get_transaction_hash(tx);
if (request.save_history && !m_wallet_state.get_wallet().save_history(tx_hash, history)) {
m_log(logging::ERROR)
<< "Saving transaction history failed, you will need to pass list of destination addresses to generate sending proof for tx="
Expand Down
4 changes: 2 additions & 2 deletions src/version.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
#pragma once

// defines are for Windows resource compiler
#define bytecoin_VERSION_WINDOWS_COMMA 3, 18, 10, 9
#define bytecoin_VERSION_STRING "3.3.2"
#define bytecoin_VERSION_WINDOWS_COMMA 3, 18, 11, 22
#define bytecoin_VERSION_STRING "3.3.3"

#ifndef RC_INVOKED // Windows resource compiler

Expand Down

0 comments on commit 7aa7714

Please sign in to comment.