chain::transaction deserialize_tx(const Iterator first)
{
    chain::transaction tx;
    auto deserial = make_deserializer_unsafe(first);
    tx.from_data(deserial);
    return tx;
}
hash_digest block_result::transaction_hash(size_t i) const
{
    BITCOIN_ASSERT(slab_);
    BITCOIN_ASSERT(i < transactions_size());
    const uint8_t* first = slab_ + 80 + 4 + 4 + i * hash_size;
    auto deserial = make_deserializer_unsafe(first);
    return deserial.read_hash();
}
void history_scan_database::scan(const address_bitset& key,
    read_function read_func, size_t from_height) const
{
    BITCOIN_ASSERT(key.size() >= settings_.sharded_bitsize);
    const hsdb_shard& shard = lookup(key);
    address_bitset sub_key = drop_prefix(key);
    auto read_wrapped = [&read_func](const uint8_t* data)
    {
        auto deserial = make_deserializer_unsafe(data);
        history_row row{
            // output or spend?
            marker_to_id(deserial.read_byte()),
            // point
            deserial.read_hash(),
            deserial.read_4_bytes(),
            // height
            deserial.read_4_bytes(),
            // value or checksum
            deserial.read_8_bytes()};
        read_func(row);
    };
    shard.scan(sub_key, read_wrapped, from_height);
}