Class: BSV::Transaction::BeefParty

Inherits:
Beef
  • Object
show all
Defined in:
lib/bsv/transaction/beef_party.rb

Overview

Transaction::Beef subclass that tracks per-party knowledge of wtxids.

Used in multi-party BEEF exchange to avoid re-transmitting transaction data and proofs that a counterparty already possesses. Each party is identified by a caller-supplied string and associated with the set of wtxids it is known to hold.

Examples:

Two-party exchange

party = BSV::Transaction::BeefParty.new(['alice', 'bob'])
party.merge_beef_from_party('alice', alice_beef)
trimmed = party.trimmed_beef_for_party('bob')  # plain Transaction::Beef

Constant Summary

Constants inherited from Beef

BSV::Transaction::Beef::ATOMIC_BEEF, BSV::Transaction::Beef::BEEF_V1, BSV::Transaction::Beef::BEEF_V2, BSV::Transaction::Beef::FORMAT_RAW_TX, BSV::Transaction::Beef::FORMAT_RAW_TX_AND_BUMP, BSV::Transaction::Beef::FORMAT_TXID_ONLY

Instance Attribute Summary

Attributes inherited from Beef

#bumps, #subject_wtxid, #transactions, #txs_not_valid, #version

Instance Method Summary collapse

Methods inherited from Beef

#clone, #find_atomic_transaction, #find_bump, #find_transaction, #find_transaction_for_signing, from_binary, from_hex, #make_txid_only, #merge, #merge_bump, #merge_raw_tx, #merge_transaction, #merge_txid_only, #sort_transactions!, #subject_dtxid, #to_atomic_binary, #to_atomic_hex, #to_binary, #to_hex, #trim_known_wtxids, #valid?, #valid_wtxids, #verify

Constructor Details

#initialize(initial_parties = []) ⇒ BeefParty

Defaults to BEEF_V2 (BRC-96) because TXID-only entries — which are central to BeefParty’s purpose — are only valid in V2. Matches the TS SDK’s new Beef() default.

Parameters:

  • initial_parties (Array<String>) (defaults to: [])

    optional initial party identifiers

Raises:

  • (ArgumentError)

    if initial_parties contains duplicates



23
24
25
26
27
# File 'lib/bsv/transaction/beef_party.rb', line 23

def initialize(initial_parties = [])
  super(version: BEEF_V2)
  @party_knowledge = {}
  initial_parties.each { |p| add_party(p) }
end

Instance Method Details

#add_known_wtxids_for_party(party_id, wtxids) ⇒ Object

Record additional wtxids as known to party_id.

Auto-creates the party if it is not yet known (TS parity). Also merges a TXID-only entry into the underlying bundle for each wtxid.

Parameters:

  • party_id (String)

    party identifier (auto-created if unknown)

  • wtxids (Array<String>)

    32-byte wire-order binary wtxids

Raises:

  • (ArgumentError)

    if any element of wtxids is not a valid wtxid



53
54
55
56
57
58
59
60
# File 'lib/bsv/transaction/beef_party.rb', line 53

def add_known_wtxids_for_party(party_id, wtxids)
  add_party(party_id) unless party?(party_id)
  wtxids.each do |wtxid|
    BSV::Primitives::Hex.validate_wtxid!(wtxid, name: 'wtxid')
    @party_knowledge[party_id].add(wtxid)
    merge_txid_only(wtxid)
  end
end

#add_party(party_id) ⇒ Object

Add a new unique party identifier.

Parameters:

  • party_id (String)

Raises:

  • (ArgumentError)

    if party_id is already known



39
40
41
42
43
# File 'lib/bsv/transaction/beef_party.rb', line 39

def add_party(party_id)
  raise ArgumentError, "duplicate party #{party_id}" if party?(party_id)

  @party_knowledge[party_id] = Set.new
end

#known_wtxids_for_party(party_id) ⇒ Array<String>

Returns 32-byte wire-order binary wtxids known to party_id.

Parameters:

  • party_id (String)

Returns:

  • (Array<String>)

    32-byte wire-order binary wtxids known to party_id

Raises:

  • (ArgumentError)

    if party_id is unknown



65
66
67
68
69
# File 'lib/bsv/transaction/beef_party.rb', line 65

def known_wtxids_for_party(party_id)
  raise ArgumentError, "unknown party #{party_id}" unless party?(party_id)

  @party_knowledge[party_id].to_a
end

#merge_beef_from_party(party_id, beef_or_binary) ⇒ Object

Merge a Transaction::Beef received from party_id.

Merges all transactions and BUMPs from beef_or_binary into self, then records the valid wtxids of the merged bundle as known to party_id. Auto-creates the party if not yet known.

Parameters:

  • party_id (String)

    party identifier

  • beef_or_binary (Transaction::Beef, String)

    a Transaction::Beef instance or raw binary BEEF bytes



80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/bsv/transaction/beef_party.rb', line 80

def merge_beef_from_party(party_id, beef_or_binary)
  beef = beef_or_binary.is_a?(Beef) ? beef_or_binary : Beef.from_binary(beef_or_binary)
  # Capture the set of wtxids the party actually sent before merging.
  beef_wtxids = beef.transactions.map(&:wtxid)
  merge(beef)
  # Record knowledge of any tx the party sent that is now provably valid
  # against the merged state. This captures the cross-bundle case where
  # an unproven tx in +beef+ becomes valid via inputs already proven in
  # +self+ (and conversely doesn't record knowledge the party never sent).
  known = valid_wtxids & beef_wtxids
  add_known_wtxids_for_party(party_id, known)
end

#party?(party_id) ⇒ Boolean

Returns true if party_id has been added.

Parameters:

  • party_id (String)

Returns:

  • (Boolean)

    true if party_id has been added



31
32
33
# File 'lib/bsv/transaction/beef_party.rb', line 31

def party?(party_id)
  @party_knowledge.key?(party_id)
end

#trimmed_beef_for_party(party_id) ⇒ Transaction::Beef

Return a new Transaction::Beef (not Transaction::BeefParty) with TXID-only entries that are known to party_id removed.

RAW_TX and RAW_TX_AND_BUMP entries are always retained even when the party knows the txid — those formats carry proof data. BUMP indices are renumbered if any unreferenced bumps are dropped.

Does not mutate self.

Parameters:

  • party_id (String)

Returns:

Raises:

  • (ArgumentError)

    if party_id is unknown



105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/bsv/transaction/beef_party.rb', line 105

def trimmed_beef_for_party(party_id)
  raise ArgumentError, "unknown party #{party_id}" unless party?(party_id)

  known = @party_knowledge[party_id].to_a

  # Build a plain Beef from our current state so trim_known_wtxids
  # returns a Beef, not a BeefParty.
  plain = Beef.new(version: @version, bumps: @bumps.dup, transactions: @transactions.dup)
  plain.instance_variable_set(:@subject_wtxid, @subject_wtxid)
  plain.instance_variable_set(:@txs_not_valid, @txs_not_valid&.dup)
  plain.trim_known_wtxids(known)
end