mirror of
https://github.com/Retropex/bitfeed.git
synced 2025-05-12 19:20:46 +02:00
101 lines
2.8 KiB
Elixir
101 lines
2.8 KiB
Elixir
Application.ensure_all_started(BitcoinStream.RPC)
|
|
|
|
require Logger
|
|
|
|
defmodule BitcoinStream.Protocol.Block do
|
|
@moduledoc """
|
|
Summarised bitcoin block.
|
|
|
|
Extends Bitcoinex.Block by computing total block value & size
|
|
and condensing transactions into only id, value and version
|
|
"""
|
|
|
|
alias BitcoinStream.Protocol.Transaction, as: BitcoinTx
|
|
alias BitcoinStream.Mempool, as: Mempool
|
|
|
|
@derive Jason.Encoder
|
|
defstruct [
|
|
:version,
|
|
:prev_block,
|
|
:merkle_root,
|
|
:timestamp,
|
|
:bits,
|
|
:bytes,
|
|
:nonce,
|
|
:txn_count,
|
|
:txns,
|
|
:fees,
|
|
:value,
|
|
:id
|
|
]
|
|
|
|
def decode(block_binary) do
|
|
with bytes <- byte_size(block_binary),
|
|
hex <- Base.encode16(block_binary, case: :lower),
|
|
{:ok, raw_block} <- Bitcoinex.Block.decode(hex),
|
|
id <- Bitcoinex.Block.block_id(block_binary),
|
|
{summarised_txns, total_value, total_fees} <- summarise_txns(raw_block.txns)
|
|
do
|
|
{:ok, %__MODULE__{
|
|
version: raw_block.version,
|
|
prev_block: raw_block.prev_block,
|
|
merkle_root: raw_block.merkle_root,
|
|
timestamp: raw_block.timestamp,
|
|
bits: raw_block.bits,
|
|
bytes: bytes,
|
|
txn_count: raw_block.txn_count,
|
|
txns: summarised_txns,
|
|
fees: total_fees,
|
|
value: total_value,
|
|
id: id
|
|
}}
|
|
else
|
|
{:error, reason} ->
|
|
Logger.error("Error decoding data for BitcoinBlock: #{reason}")
|
|
:error
|
|
_ ->
|
|
Logger.error("Error decoding data for BitcoinBlock: (unknown reason)")
|
|
:error
|
|
end
|
|
end
|
|
|
|
defp summarise_txns([coinbase | txns]) do
|
|
# Mempool.is_done returns false while the mempool is still syncing
|
|
with extended_coinbase <- BitcoinTx.extend(coinbase),
|
|
{summarised, total, fees} <- summarise_txns(txns, [], 0, 0, Mempool.is_done(:mempool)) do
|
|
{[extended_coinbase | summarised], total, fees}
|
|
else
|
|
err ->
|
|
Logger.error("Failed to inflate block");
|
|
Logger.error(err);
|
|
:error
|
|
end
|
|
end
|
|
|
|
defp summarise_txns([], summarised, total, fees, do_inflate) do
|
|
if do_inflate do
|
|
{Enum.reverse(summarised), total, fees}
|
|
else
|
|
{Enum.reverse(summarised), total, nil}
|
|
end
|
|
end
|
|
|
|
defp summarise_txns([next | rest], summarised, total, fees, do_inflate) do
|
|
extended_txn = BitcoinTx.extend(next)
|
|
|
|
# if the mempool is still syncing, inflating txs will take too long, so skip it
|
|
if do_inflate do
|
|
inflated_txn = BitcoinTx.inflate(extended_txn, false)
|
|
if (inflated_txn.inflated) do
|
|
Logger.debug("Processing block tx #{length(summarised)}/#{length(summarised) + length(rest) + 1} | #{extended_txn.id}");
|
|
summarise_txns(rest, [inflated_txn | summarised], total + inflated_txn.value, fees + inflated_txn.fee, true)
|
|
else
|
|
summarise_txns(rest, [inflated_txn | summarised], total + inflated_txn.value, nil, false)
|
|
end
|
|
else
|
|
summarise_txns(rest, [extended_txn | summarised], total + extended_txn.value, nil, false)
|
|
end
|
|
end
|
|
|
|
end
|