View in context in the libbitcoin Slack #general mirror.
void executor::read_test(bool dump) const
{
constexpr auto start_tx = 1'000'000'000_u32;
constexpr auto target_count = 100_size;
// Set ensures unique addresses.
std::set<hash_digest> keys{};
auto tx = start_tx;
logger(format("Getting first [%1%] output address hashes.") % target_count);
auto start = fine_clock::now();
while (!cancel_ && keys.size() < target_count)
{
const auto outputs = query_.get_outputs(tx++);
if (outputs->empty())
return;
for (const auto& put: *outputs)
{
keys.emplace(put->script().hash());
if (cancel_ || keys.size() == target_count)
break;
}
}
auto span = duration_cast<milliseconds>(fine_clock::now() - start);
logger(format("Got first [%1%] unique addresses above tx [%2%] in [%3%] ms.") %
keys.size() % start_tx % span.count());
struct out
{
hash_digest address;
uint32_t bk_fk;
uint32_t bk_height;
hash_digest bk_hash;
uint32_t tx_fk;
size_t tx_position;
hash_digest tx_hash;
uint32_t sp_tx_fk;
hash_digest sp_tx_hash;
uint64_t input_fk;
chain::input::cptr input{};
uint64_t output_fk;
chain::output::cptr output{};
};
std_vector<out> outs{};
outs.reserve(target_count);
using namespace database;
start = fine_clock::now();
for (auto& key: keys)
{
size_t found{};
auto address_it = store_.address.it(key);
if (cancel_ || address_it.self().is_terminal())
return;
do
{
table::address::record address{};
if (cancel_ || !store_.address.get(address_it.self(), address))
return;
const auto out_fk = address.output_fk;
table::output::get_parent output{};
if (!store_.output.get(out_fk, output))
return;
const auto tx_fk = output.parent_fk;
const auto block_fk = query_.to_block(tx_fk);
table::header::get_height header{};
if (!store_.header.get(block_fk, header))
return;
table::txs::get_position txs{ {}, tx_fk };
if (!store_.txs.get(query_.to_txs(block_fk), txs))
return;
spend_link sp_fk{};
input_link in_fk{};
tx_link sp_tx_fk{};
// Get first spender only (may or may not be confirmed).
const auto spenders = query_.to_spenders(out_fk);
if (!spenders.empty())
{
sp_fk = spenders.front();
table::spend::record spend{};
if (!store_.spend.get(sp_fk, spend))
return;
in_fk = spend.input_fk;
sp_tx_fk = spend.parent_fk;
}
++found;
outs.push_back(out
{
key,
block_fk,
header.height,
query_.get_header_key(block_fk),
tx_fk,
txs.position,
query_.get_tx_key(tx_fk),
sp_tx_fk,
query_.get_tx_key(sp_tx_fk),
in_fk,
query_.get_input(sp_fk),
out_fk,
query_.get_output(out_fk)
});
}
while (address_it.advance());
logger(format("Fetched [%1%] unique payments to address [%2%].") %
found% encode_hash(key));
}
span = duration_cast<milliseconds>(fine_clock::now() - start);
logger(format("Got all [%1%] payments to [%2%] addresses in [%3%] ms.") %
outs.size() % keys.size() % span.count());
if (!dump)
return;
// Write it all...
logger(
"output_script_hash, "
"ouput_bk_fk, "
"ouput_bk_height, "
"ouput_bk_hash, "
"ouput_tx_fk, "
"ouput_tx_position, "
"ouput_tx_hash, "
"input_tx_fk, "
"input_tx_hash, "
"output_fk, "
"output_script, "
"input_fk, "
"input_script"
);
for (const auto& row: outs)
{
if (cancel_) break;
const auto output = !row.output ? "{error}" :
row.output->script().to_string(chain::flags::all_rules);
const auto input = !row.input ? "{unspent}" :
row.input->script().to_string(chain::flags::all_rules);
logger(format("%1%, %2%, %3%, %4%, %5%, %6%, %7%, %8%, %9%, %10%, %11%, %12%, %13%") %
encode_hash(row.address) %
row.bk_fk %
row.bk_height %
encode_hash(row.bk_hash) %
row.tx_fk %
row.tx_position %
encode_hash(row.tx_hash) %
row.sp_tx_fk %
encode_hash(row.sp_tx_hash) %
row.output_fk %
output %
row.input_fk %
input);
}
}