Class: BSV::Network::ChainTracker

Inherits:
Transaction::ChainTracker
  • Object
show all
Defined in:
lib/bsv/network/chain_tracker.rb

Overview

Write-through chain tracker backed by the blocks table and the Services routing layer. Satisfies the SDK’s Transaction::ChainTracker duck type so it can be passed to Transaction#verify.

Fast path: look up the block by height in the local blocks table. Miss path: fetch the header from the network via Services, persist it, then answer.

Fails closed: any error returns false — verification fails rather than passing on incomplete data.

Instance Method Summary collapse

Constructor Details

#initialize(db:, services:) ⇒ ChainTracker

Returns a new instance of ChainTracker.

Parameters:

  • db (Sequel::Database)

    database handle with a blocks table

  • services (BSV::Network::Services)

    routing layer for network calls



18
19
20
21
22
# File 'lib/bsv/network/chain_tracker.rb', line 18

def initialize(db:, services:)
  super()
  @db = db
  @services = services
end

Instance Method Details

#current_heightInteger

Return the current blockchain height.

Returns:

  • (Integer)


56
57
58
59
60
61
62
63
# File 'lib/bsv/network/chain_tracker.rb', line 56

def current_height
  result = @services.call(:current_height)
  return result.data if result.http_success?

  @db[:blocks].max(:height) || 0
rescue StandardError
  @db[:blocks].max(:height) || 0
end

#valid_root_for_height?(root, height) ⇒ Boolean

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

Parameters:

  • root (String)

    merkle root as a hex string (from SDK’s MerklePath#verify)

  • height (Integer)

    block height

Returns:

  • (Boolean)


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/bsv/network/chain_tracker.rb', line 29

def valid_root_for_height?(root, height)
  root_bin = [root].pack('H*')

  # Fast path: local blocks table
  block = @db[:blocks].where(height: height).first
  return block[:merkle_root] == root_bin if block

  # Miss path: fetch header via Services routing layer
  result = @services.call(:get_block_header, height)
  return false unless result.http_success?

  # Provider field names vary: WoC uses 'merkleroot', Chaintracks uses 'merkleRoot'
  fetched_root = result.data['merkleroot'] || result.data['merkleRoot'] || result.data['merkle_root']
  return false unless fetched_root

  block_hash = result.data['hash'] || result.data['blockHash'] || result.data['block_hash']
  persist_block(height: height, merkle_root: fetched_root, block_hash: block_hash)

  [fetched_root].pack('H*') == root_bin
rescue StandardError => e
  BSV.logger&.warn { "[ChainTracker] valid_root_for_height? error: #{e.message}" }
  false
end