MCPcopy Create free account
hub / github.com/bcndev/bytecoin / get_random_outputs

Method get_random_outputs

src/Core/BlockChainState.cpp:1093–1163  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1091}
1092
1093std::vector<api::Output> BlockChainState::get_random_outputs(uint8_t block_major_version, Amount amount,
1094 size_t output_count, Height confirmed_height, Timestamp block_timestamp, Timestamp block_median_timestamp) const {
1095 std::vector<api::Output> result;
1096 std::vector<api::Output> spent_result;
1097 size_t total_stack_count = next_stack_index_for_amount(amount);
1098 // We might need better algorithm if we have lots of locked amounts
1099 std::set<size_t> tried_or_added;
1100
1101 size_t attempts = 0;
1102 if (total_stack_count > output_count) // implicit total_stack_count > 0
1103 for (; result.size() < output_count && attempts < output_count * 20; ++attempts) { // TODO - 20
1104 const size_t num = m_currency.mixin_distribution(amount, total_stack_count);
1105 if (!tried_or_added.insert(num).second)
1106 continue;
1107 size_t global_index = 0;
1108 invariant(read_hidden_amount_map(amount, num, &global_index), "");
1109 OutputIndexData unp;
1110 invariant(read_hidden_amount_output(global_index, &unp), "num < total_count not found");
1111 if (unp.height > confirmed_height) {
1112 if (confirmed_height + 128 < get_tip_height())
1113 total_stack_count = num;
1114 // heuristic - if confirmed_height is deep, the area under ditribution curve
1115 // with height < confirmed_height might be very small, so we adjust total_count
1116 // to get descent results after small number of attempts
1117 continue;
1118 }
1119 if (!m_currency.is_transaction_unlocked(block_major_version, unp.unlock_block_or_timestamp,
1120 confirmed_height, block_timestamp, block_median_timestamp))
1121 continue;
1122 if (unp.spent && spent_result.size() >= output_count)
1123 continue; // We need only so much spent
1124 api::Output item;
1125 item.amount = amount;
1126 item.stack_index = num;
1127 item.global_index = global_index;
1128 item.unlock_block_or_timestamp = unp.unlock_block_or_timestamp;
1129 item.public_key = unp.public_key;
1130 item.height = unp.height;
1131 (unp.spent ? spent_result : result).push_back(item);
1132 }
1133 if (result.size() < output_count) {
1134 // Read the whole index.
1135 attempts = 0;
1136 for (DB::Cursor cur = m_db.rbegin(AMOUNT_OUTPUT_PREFIX + common::write_varint_sqlite4(amount));
1137 result.size() < output_count && attempts < 10000 && !cur.end(); cur.next(), ++attempts) { // TODO - 10000
1138 const size_t stack_index = common::integer_cast<size_t>(common::read_varint_sqlite4(cur.get_suffix()));
1139 if (tried_or_added.count(stack_index) != 0)
1140 continue;
1141 size_t global_index = 0;
1142 seria::from_binary(global_index, cur.get_value_array());
1143 OutputIndexData unp;
1144 invariant(read_hidden_amount_output(global_index, &unp), "");
1145 if (unp.height > confirmed_height)
1146 continue;
1147 if (!m_currency.is_transaction_unlocked(block_major_version, unp.unlock_block_or_timestamp,
1148 confirmed_height, block_timestamp, block_median_timestamp))
1149 continue;
1150 if (unp.spent && spent_result.size() >= output_count)

Callers 1

on_get_random_outputsMethod · 0.80

Calls 10

write_varint_sqlite4Function · 0.85
from_binaryFunction · 0.85
mixin_distributionMethod · 0.80
read_varint_sqlite4Function · 0.50
sizeMethod · 0.45
rbeginMethod · 0.45
endMethod · 0.45
nextMethod · 0.45
get_value_arrayMethod · 0.45

Tested by

no test coverage detected