Skip to content

Class BSV::Transaction::ChainTracker

Inherits: Object

Duck type for block header lookups used by the SDK's verify methods.

{Beef#verify}, {MerklePath#verify}, and {Tx#verify} define what a valid structure is — they walk trees, check proofs, and compare roots. But they have no data source of their own. The chain tracker is the data source: an object the consumer provides that can answer "is this merkle root valid for this block height?"

This class is a working default implementation that wraps a {BSV::Network::Provider} and dispatches via {Provider#call}. The provider must serve the :get_block_header and :current_height commands (e.g. a provider configured with {Protocols::JungleBus}).

Subclasses may override either or both methods to supply their own data source (in-memory hash, database cache, etc.) without touching the provider at all. The provider argument is optional precisely to preserve this pattern — a subclass that overrides both methods never reaches the provider-dispatch path.

Any object responding to valid_root_for_height? and current_height satisfies this interface. Inheriting from this class is optional — it exists to document the contract and provide a ready-to-use provider-backed implementation.

@example In-memory chain tracker (test / declarative)

class HashTracker < BSV::Transaction::ChainTracker
  def initialize(headers)  @headers = headers end
  def valid_root_for_height?(root, h) @headers[h] == root end
  def current_height() @headers.keys.max end
end
tracker = HashTracker.new(800_000 => 'abcd...')

@example Cache-aware chain tracker (production / imperative)

class WalletChainTracker < BSV::Transaction::ChainTracker
  def valid_root_for_height?(root, height)
    header = @db.find_header(height) || fetch_and_store(height)
    header.merkle_root == root
  end
end

@example Provider-backed (default impl)

tracker = BSV::Transaction::ChainTracker.default
tracker.valid_root_for_height?('abcd...', 800_000)

@example Testnet

tracker = BSV::Transaction::ChainTracker.default(testnet: true)
tracker.current_height

Attributes

provider [R]

  • @return [BSV::Network::Provider, nil] the underlying provider, if any

Public Class Methods

default(testnet: = false)

Return a default ChainTracker backed by the GorillaPool provider. - @param testnet [Boolean] when true, uses the testnet provider - @return [Transaction::ChainTracker]

Public Instance Methods

current_height()

Return the current blockchain height.

Dispatches :current_height to the configured provider. - @raise [RuntimeError] when no provider is configured - @raise [RuntimeError] on network or API error - @return [Integer] the height of the chain tip

initialize(provider = nil)

  • @param provider [BSV::Network::Provider, nil] provider serving +:get_block_header+ and +:current_height+. Optional when the subclass overrides both methods.
  • @return [ChainTracker] a new instance of ChainTracker

valid_root_for_height?(root, height)

Verify that a merkle root is valid for the given block height.

Dispatches :get_block_header to the configured provider. Returns false on 404 (block not found). Relies on the wire-protocol classes that expose :get_block_header (Protocols::JungleBus, Protocols::Chaintracks, Protocols::WoCREST) to emit the canonical merkle_root key — see issue #791 for the Pattern A normalisation that absorbed the previous field-name shim. - @param root [String] merkle root as a hex string - @param height [Integer] block height - @raise [RuntimeError] when no provider is configured - @raise [RuntimeError] on network or API error - @return [Boolean] true if the root matches the block at the given height