bsv-sdk 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/lib/bsv/auth/certificate.rb +6 -2
- data/lib/bsv/identity/client.rb +1 -0
- data/lib/bsv/mcp/tools/broadcast_p2pkh.rb +2 -2
- data/lib/bsv/mcp/tools/helpers.rb +2 -2
- data/lib/bsv/network/broadcast_error.rb +1 -0
- data/lib/bsv/network/broadcast_response.rb +1 -0
- data/lib/bsv/network/protocols/arc.rb +4 -3
- data/lib/bsv/network/protocols/taal_binary.rb +1 -0
- data/lib/bsv/network/protocols/woc_rest.rb +2 -1
- data/lib/bsv/overlay/lookup_resolver.rb +1 -0
- data/lib/bsv/overlay/topic_broadcaster.rb +1 -1
- data/lib/bsv/overlay/types.rb +1 -0
- data/lib/bsv/primitives/hex.rb +64 -0
- data/lib/bsv/registry/client.rb +3 -1
- data/lib/bsv/registry/types.rb +1 -0
- data/lib/bsv/script/interpreter/interpreter.rb +7 -0
- data/lib/bsv/script/interpreter/operations/crypto.rb +7 -1
- data/lib/bsv/transaction/beef.rb +122 -83
- data/lib/bsv/transaction/merkle_path.rb +54 -38
- data/lib/bsv/transaction/transaction.rb +81 -30
- data/lib/bsv/transaction/transaction_input.rb +23 -18
- data/lib/bsv/version.rb +1 -1
- data/lib/bsv/wallet/interface/brc100.rb +5 -2
- data/lib/bsv/wallet/proto_wallet/key_deriver.rb +2 -0
- data/lib/bsv/wallet/proto_wallet.rb +6 -0
- data/lib/bsv-sdk.rb +14 -0
- metadata +1 -1
|
@@ -329,6 +329,11 @@ module BSV
|
|
|
329
329
|
ancestors = collect_ancestors
|
|
330
330
|
|
|
331
331
|
bump_index_by_height = build_beef_bumps(beef, ancestors)
|
|
332
|
+
BSV.logger&.debug do
|
|
333
|
+
proven = ancestors.count(&:merkle_path)
|
|
334
|
+
"[Transaction] BEEF: #{ancestors.length} ancestors, #{proven} proven " \
|
|
335
|
+
"across #{bump_index_by_height.length} block heights"
|
|
336
|
+
end
|
|
332
337
|
|
|
333
338
|
ancestors.each do |tx|
|
|
334
339
|
entry = if tx.merkle_path
|
|
@@ -370,11 +375,11 @@ module BSV
|
|
|
370
375
|
# or nil if the BEEF is empty or contains no raw transaction entries
|
|
371
376
|
def self.from_beef(data)
|
|
372
377
|
beef = Beef.from_binary(data)
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
return nil unless
|
|
378
|
+
subject_wtxid = beef.subject_wtxid ||
|
|
379
|
+
beef.transactions.reverse.find(&:transaction)&.transaction&.wtxid
|
|
380
|
+
return nil unless subject_wtxid
|
|
376
381
|
|
|
377
|
-
beef.find_atomic_transaction(
|
|
382
|
+
beef.find_atomic_transaction(subject_wtxid)
|
|
378
383
|
end
|
|
379
384
|
|
|
380
385
|
# Parse a BEEF hex string and return the subject transaction.
|
|
@@ -388,15 +393,26 @@ module BSV
|
|
|
388
393
|
|
|
389
394
|
# --- Transaction ID ---
|
|
390
395
|
|
|
391
|
-
#
|
|
396
|
+
# Wire-order transaction ID (raw SHA-256d of the serialised tx).
|
|
397
|
+
#
|
|
398
|
+
# Used by BEEF, BUMPs, and merkle paths, which all work in wire byte order
|
|
399
|
+
# to match {TransactionInput#prev_wtxid}.
|
|
400
|
+
#
|
|
401
|
+
# @return [String] 32-byte transaction ID in wire byte order
|
|
402
|
+
def wtxid
|
|
403
|
+
id = BSV::Primitives::Digest.sha256d(to_binary)
|
|
404
|
+
BSV.logger&.debug { "[Transaction] wtxid computed (dtxid=#{id.reverse.unpack1('H*')})" }
|
|
405
|
+
id
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# Display-order transaction ID (reversed from the natural SHA-256d hash).
|
|
392
409
|
#
|
|
393
|
-
#
|
|
394
|
-
#
|
|
395
|
-
# order (natural hash). Use +.reverse+ to convert between the two.
|
|
410
|
+
# This is the conventional human-readable representation used in block
|
|
411
|
+
# explorers, wallets, and all user-facing contexts.
|
|
396
412
|
#
|
|
397
413
|
# @return [String] 32-byte transaction ID in display byte order
|
|
398
414
|
def txid
|
|
399
|
-
|
|
415
|
+
wtxid.reverse
|
|
400
416
|
end
|
|
401
417
|
|
|
402
418
|
# The transaction ID as a hex string (display byte order).
|
|
@@ -406,6 +422,19 @@ module BSV
|
|
|
406
422
|
txid.unpack1('H*')
|
|
407
423
|
end
|
|
408
424
|
|
|
425
|
+
# Display-order transaction ID as a hex string.
|
|
426
|
+
#
|
|
427
|
+
# Mirrors the wallet gem's +DisplayTxid+ pattern. +dtxid+ always returns
|
|
428
|
+
# a 64-char hex string suitable for JSON and UI boundaries.
|
|
429
|
+
#
|
|
430
|
+
# @return [String] hex-encoded transaction ID (display order)
|
|
431
|
+
alias dtxid txid_hex
|
|
432
|
+
|
|
433
|
+
# Display-order transaction ID as a hex string (alias for {#dtxid}).
|
|
434
|
+
#
|
|
435
|
+
# @return [String] hex-encoded transaction ID (display order)
|
|
436
|
+
alias dtxid_hex txid_hex
|
|
437
|
+
|
|
409
438
|
# --- Sighash (BIP-143 with FORKID) ---
|
|
410
439
|
|
|
411
440
|
# Build the BIP-143 sighash preimage for an input.
|
|
@@ -456,6 +485,19 @@ module BSV
|
|
|
456
485
|
# 10. sighash type (4 LE) — includes FORKID flag
|
|
457
486
|
buf << [sighash_type].pack('V')
|
|
458
487
|
|
|
488
|
+
BSV.logger&.debug do
|
|
489
|
+
hp = buf.byteslice(4, 32).unpack1('H*')
|
|
490
|
+
hs = buf.byteslice(36, 32).unpack1('H*')
|
|
491
|
+
op = input.outpoint_binary.unpack1('H*')
|
|
492
|
+
sc = script_bytes.unpack1('H*')
|
|
493
|
+
ho = buf.byteslice(-40, 32).unpack1('H*')
|
|
494
|
+
"[Sighash] input=#{input_index} type=0x#{format('%02x', sighash_type)} " \
|
|
495
|
+
"version=#{@version} hashPrevouts=#{hp} hashSequence=#{hs} " \
|
|
496
|
+
"outpoint=#{op} scriptCode=#{sc[0, 40]}#{'...' if sc.length > 40} " \
|
|
497
|
+
"value=#{input.source_satoshis} seq=#{input.sequence} " \
|
|
498
|
+
"hashOutputs=#{ho} locktime=#{@lock_time}"
|
|
499
|
+
end
|
|
500
|
+
|
|
459
501
|
buf
|
|
460
502
|
end
|
|
461
503
|
|
|
@@ -466,7 +508,9 @@ module BSV
|
|
|
466
508
|
# @param subscript [Script::Script, nil] override locking script for the input
|
|
467
509
|
# @return [String] 32-byte sighash digest
|
|
468
510
|
def sighash(input_index, sighash_type = Sighash::ALL_FORK_ID, subscript: nil)
|
|
469
|
-
BSV::Primitives::Digest.sha256d(sighash_preimage(input_index, sighash_type, subscript: subscript))
|
|
511
|
+
digest = BSV::Primitives::Digest.sha256d(sighash_preimage(input_index, sighash_type, subscript: subscript))
|
|
512
|
+
BSV.logger&.debug { "[Sighash] digest=#{digest.unpack1('H*')}" }
|
|
513
|
+
digest
|
|
470
514
|
end
|
|
471
515
|
|
|
472
516
|
# --- Signing ---
|
|
@@ -580,17 +624,17 @@ module BSV
|
|
|
580
624
|
|
|
581
625
|
until queue.empty?
|
|
582
626
|
tx = queue.shift
|
|
583
|
-
|
|
584
|
-
next if verified[
|
|
627
|
+
wtxid = tx.wtxid
|
|
628
|
+
next if verified[wtxid]
|
|
585
629
|
|
|
586
630
|
# Merkle path short-circuit: proven transaction needs no input verification
|
|
587
631
|
if tx.merkle_path
|
|
588
|
-
unless tx.merkle_path.verify(
|
|
632
|
+
unless tx.merkle_path.verify(tx.txid_hex, chain_tracker)
|
|
589
633
|
raise VerificationError.new(:invalid_merkle_proof,
|
|
590
|
-
"invalid merkle proof for transaction #{
|
|
634
|
+
"invalid merkle proof for transaction #{tx.txid_hex}")
|
|
591
635
|
end
|
|
592
636
|
|
|
593
|
-
verified[
|
|
637
|
+
verified[wtxid] = true
|
|
594
638
|
next
|
|
595
639
|
end
|
|
596
640
|
|
|
@@ -622,13 +666,13 @@ module BSV
|
|
|
622
666
|
|
|
623
667
|
# Enqueue source transaction for verification if not yet verified
|
|
624
668
|
source_tx = input.source_transaction
|
|
625
|
-
queue << source_tx if source_tx && !verified[source_tx.
|
|
669
|
+
queue << source_tx if source_tx && !verified[source_tx.wtxid]
|
|
626
670
|
end
|
|
627
671
|
|
|
628
672
|
# Output ≤ input check
|
|
629
673
|
verify_output_constraint(tx)
|
|
630
674
|
|
|
631
|
-
verified[
|
|
675
|
+
verified[wtxid] = true
|
|
632
676
|
end
|
|
633
677
|
|
|
634
678
|
true
|
|
@@ -777,19 +821,19 @@ module BSV
|
|
|
777
821
|
end
|
|
778
822
|
|
|
779
823
|
def verify_input_requirements(tx, input, index)
|
|
780
|
-
|
|
824
|
+
dtxid_hex = tx.txid_hex
|
|
781
825
|
if input.unlocking_script.nil?
|
|
782
826
|
raise VerificationError.new(:missing_source,
|
|
783
|
-
"input #{index} of transaction #{
|
|
827
|
+
"input #{index} of transaction #{dtxid_hex} has no unlocking script")
|
|
784
828
|
end
|
|
785
829
|
if input.source_locking_script.nil?
|
|
786
830
|
raise VerificationError.new(:missing_source,
|
|
787
|
-
"input #{index} of transaction #{
|
|
831
|
+
"input #{index} of transaction #{dtxid_hex} has no source locking script")
|
|
788
832
|
end
|
|
789
833
|
return unless input.source_satoshis.nil?
|
|
790
834
|
|
|
791
835
|
raise VerificationError.new(:missing_source,
|
|
792
|
-
"input #{index} of transaction #{
|
|
836
|
+
"input #{index} of transaction #{dtxid_hex} has no source satoshis")
|
|
793
837
|
end
|
|
794
838
|
|
|
795
839
|
def verify_fee(fee_model)
|
|
@@ -843,7 +887,7 @@ module BSV
|
|
|
843
887
|
|
|
844
888
|
# Collect this transaction and all its ancestors in dependency order
|
|
845
889
|
# (ancestors first, self last). Stops recursion at transactions with
|
|
846
|
-
# a merkle_path (proven leaves). Deduplicates by
|
|
890
|
+
# a merkle_path (proven leaves). Deduplicates by wtxid (wire-order bytes).
|
|
847
891
|
def collect_ancestors
|
|
848
892
|
seen = {}
|
|
849
893
|
result = []
|
|
@@ -852,18 +896,25 @@ module BSV
|
|
|
852
896
|
end
|
|
853
897
|
|
|
854
898
|
def collect_ancestors_recursive(tx, seen, result)
|
|
855
|
-
|
|
856
|
-
return if seen.key?(
|
|
899
|
+
wtxid = tx.wtxid
|
|
900
|
+
return if seen.key?(wtxid)
|
|
857
901
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
902
|
+
if tx.merkle_path
|
|
903
|
+
BSV.logger&.debug do
|
|
904
|
+
"[Transaction] ancestor: #{tx.dtxid_hex} proven at height #{tx.merkle_path.block_height} (leaf stop)"
|
|
905
|
+
end
|
|
906
|
+
else
|
|
907
|
+
tx.inputs.each_with_index do |input, idx|
|
|
908
|
+
unless input.source_transaction
|
|
909
|
+
BSV.logger&.debug { "[Transaction] ancestor: #{tx.dtxid_hex} input #{idx} has no source_transaction (skipped)" }
|
|
910
|
+
next
|
|
911
|
+
end
|
|
861
912
|
|
|
862
913
|
collect_ancestors_recursive(input.source_transaction, seen, result)
|
|
863
914
|
end
|
|
864
915
|
end
|
|
865
916
|
|
|
866
|
-
seen[
|
|
917
|
+
seen[wtxid] = true
|
|
867
918
|
result << tx
|
|
868
919
|
end
|
|
869
920
|
|
|
@@ -886,8 +937,8 @@ module BSV
|
|
|
886
937
|
merged = txs.first.merkle_path.dup
|
|
887
938
|
txs.drop(1).each { |t| merged.combine(t.merkle_path) }
|
|
888
939
|
|
|
889
|
-
|
|
890
|
-
clean = merged.extract(
|
|
940
|
+
wtxid_hashes = txs.map(&:wtxid)
|
|
941
|
+
clean = merged.extract(wtxid_hashes)
|
|
891
942
|
|
|
892
943
|
bump_index_by_height[height] = beef.bumps.length
|
|
893
944
|
beef.bumps << clean
|
|
@@ -8,8 +8,8 @@ module BSV
|
|
|
8
8
|
# output index (the "outpoint"), and provide an unlocking script to
|
|
9
9
|
# satisfy the locking script conditions.
|
|
10
10
|
class TransactionInput
|
|
11
|
-
# @return [String] 32-byte transaction ID of the output being spent
|
|
12
|
-
attr_reader :
|
|
11
|
+
# @return [String] 32-byte wire-order transaction ID of the output being spent
|
|
12
|
+
attr_reader :prev_wtxid
|
|
13
13
|
|
|
14
14
|
# @return [Integer] index of the output within the previous transaction
|
|
15
15
|
attr_reader :prev_tx_out_index
|
|
@@ -32,15 +32,17 @@ module BSV
|
|
|
32
32
|
# @return [UnlockingScriptTemplate, nil] template for deferred signing
|
|
33
33
|
attr_accessor :unlocking_script_template
|
|
34
34
|
|
|
35
|
-
# @param
|
|
35
|
+
# @param prev_wtxid [String] 32-byte wire-order transaction ID
|
|
36
36
|
# @param prev_tx_out_index [Integer] output index in the previous transaction
|
|
37
37
|
# @param unlocking_script [Script::Script, nil] unlocking script (nil if unsigned)
|
|
38
38
|
# @param sequence [Integer] sequence number
|
|
39
|
-
def initialize(
|
|
40
|
-
|
|
39
|
+
def initialize(prev_wtxid:, prev_tx_out_index:, unlocking_script: nil, sequence: 0xFFFFFFFF)
|
|
40
|
+
BSV::Primitives::Hex.validate_wtxid!(prev_wtxid, name: 'prev_wtxid')
|
|
41
|
+
@prev_wtxid = prev_wtxid.b
|
|
41
42
|
@prev_tx_out_index = prev_tx_out_index
|
|
42
43
|
@unlocking_script = unlocking_script
|
|
43
44
|
@sequence = sequence
|
|
45
|
+
BSV.logger&.debug { "[TransactionInput] prev_wtxid set: #{dtxid_hex}:#{@prev_tx_out_index}" }
|
|
44
46
|
end
|
|
45
47
|
|
|
46
48
|
# Serialise the input to its binary wire format.
|
|
@@ -48,7 +50,7 @@ module BSV
|
|
|
48
50
|
# @return [String] binary input (outpoint + varint + script + sequence)
|
|
49
51
|
def to_binary
|
|
50
52
|
script_bytes = @unlocking_script ? @unlocking_script.to_binary : ''.b
|
|
51
|
-
@
|
|
53
|
+
@prev_wtxid +
|
|
52
54
|
[@prev_tx_out_index].pack('V') +
|
|
53
55
|
VarInt.encode(script_bytes.bytesize) +
|
|
54
56
|
script_bytes +
|
|
@@ -66,7 +68,7 @@ module BSV
|
|
|
66
68
|
"truncated input: need 36 bytes for outpoint at offset #{offset}, got #{data.bytesize - offset}"
|
|
67
69
|
end
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
prev_wtxid = data.byteslice(offset, 32)
|
|
70
72
|
prev_tx_out_index = data.byteslice(offset + 32, 4).unpack1('V')
|
|
71
73
|
offset += 36
|
|
72
74
|
|
|
@@ -90,7 +92,7 @@ module BSV
|
|
|
90
92
|
|
|
91
93
|
total = 36 + vi_size + script_len + 4
|
|
92
94
|
input = new(
|
|
93
|
-
|
|
95
|
+
prev_wtxid: prev_wtxid,
|
|
94
96
|
prev_tx_out_index: prev_tx_out_index,
|
|
95
97
|
unlocking_script: unlocking_script,
|
|
96
98
|
sequence: sequence
|
|
@@ -98,26 +100,29 @@ module BSV
|
|
|
98
100
|
[input, total]
|
|
99
101
|
end
|
|
100
102
|
|
|
101
|
-
# Convert a hex transaction ID to
|
|
103
|
+
# Convert a display-order hex transaction ID to wire-order bytes.
|
|
102
104
|
#
|
|
103
105
|
# @param hex [String] hex-encoded transaction ID (display order)
|
|
104
|
-
# @return [String] 32-byte transaction ID in
|
|
105
|
-
def self.
|
|
106
|
-
|
|
106
|
+
# @return [String] 32-byte transaction ID in wire byte order
|
|
107
|
+
def self.wtxid_from_hex(hex)
|
|
108
|
+
BSV::Primitives::Hex.validate_dtxid_hex!(hex, name: 'wtxid_from_hex input')
|
|
109
|
+
wtxid = [hex].pack('H*').reverse
|
|
110
|
+
BSV.logger&.debug { "[TransactionInput] wtxid_from_hex: #{hex} -> #{wtxid.bytesize}B wire-order" }
|
|
111
|
+
wtxid
|
|
107
112
|
end
|
|
108
113
|
|
|
109
|
-
# Serialise the outpoint (
|
|
114
|
+
# Serialise the outpoint (prev_wtxid + output index) as binary.
|
|
110
115
|
#
|
|
111
116
|
# @return [String] 36-byte outpoint
|
|
112
117
|
def outpoint_binary
|
|
113
|
-
@
|
|
118
|
+
@prev_wtxid + [@prev_tx_out_index].pack('V')
|
|
114
119
|
end
|
|
115
120
|
|
|
116
|
-
# The previous transaction ID in
|
|
121
|
+
# The previous transaction ID in display-order hex.
|
|
117
122
|
#
|
|
118
|
-
# @return [String] hex-encoded transaction ID
|
|
119
|
-
def
|
|
120
|
-
@
|
|
123
|
+
# @return [String] hex-encoded transaction ID (display order)
|
|
124
|
+
def dtxid_hex
|
|
125
|
+
@prev_wtxid.reverse.unpack1('H*')
|
|
121
126
|
end
|
|
122
127
|
end
|
|
123
128
|
end
|
data/lib/bsv/version.rb
CHANGED
|
@@ -38,10 +38,12 @@ module BSV
|
|
|
38
38
|
# - :basket [String] optional basket name for UTXO tracking
|
|
39
39
|
# - :custom_instructions [String] application-specific context
|
|
40
40
|
# - :tags [Array<String>] output tags for filtering
|
|
41
|
-
# @return [Hash] :txid, :tx, :no_send_change,
|
|
41
|
+
# @return [Hash] BRC-100 spec-mandated keys: :txid (display-order hex), :tx, :no_send_change,
|
|
42
|
+
# :send_with_results, :signable_transaction
|
|
42
43
|
def create_action(description:, input_beef: nil, inputs: nil, outputs: nil,
|
|
43
44
|
lock_time: nil, version: nil, labels: nil,
|
|
44
45
|
sign_and_process: true, accept_delayed_broadcast: true,
|
|
46
|
+
# BRC-100 spec-mandated parameter names — display-order hex txids
|
|
45
47
|
trust_self: nil, known_txids: nil, return_txid_only: false,
|
|
46
48
|
no_send: false, no_send_change: nil, send_with: nil,
|
|
47
49
|
randomize_outputs: true, originator: nil)
|
|
@@ -53,7 +55,8 @@ module BSV
|
|
|
53
55
|
# @param spends [Hash{Integer => Hash}] input index => { unlocking_script:, sequence_number: }
|
|
54
56
|
# @param reference [String] reference returned by {#create_action}
|
|
55
57
|
def sign_action(spends:, reference:,
|
|
56
|
-
accept_delayed_broadcast: true,
|
|
58
|
+
accept_delayed_broadcast: true,
|
|
59
|
+
return_txid_only: false, # BRC-100 spec-mandated parameter name
|
|
57
60
|
no_send: false, send_with: nil, originator: nil)
|
|
58
61
|
raise NotImplementedError
|
|
59
62
|
end
|
|
@@ -45,6 +45,7 @@ module BSV
|
|
|
45
45
|
Validators.validate_protocol_id!(protocol_id)
|
|
46
46
|
Validators.validate_key_id!(key_id)
|
|
47
47
|
invoice = compute_invoice_number(protocol_id, key_id)
|
|
48
|
+
BSV.logger&.debug { "[KeyDeriver] derive_public_key: invoice=#{invoice.inspect} for_self=#{for_self}" }
|
|
48
49
|
counterparty_pub = resolve_counterparty(counterparty)
|
|
49
50
|
|
|
50
51
|
if for_self
|
|
@@ -64,6 +65,7 @@ module BSV
|
|
|
64
65
|
Validators.validate_protocol_id!(protocol_id)
|
|
65
66
|
Validators.validate_key_id!(key_id)
|
|
66
67
|
invoice = compute_invoice_number(protocol_id, key_id)
|
|
68
|
+
BSV.logger&.debug { "[KeyDeriver] derive_private_key: invoice=#{invoice.inspect}" }
|
|
67
69
|
counterparty_pub = resolve_counterparty(counterparty)
|
|
68
70
|
@root_key.derive_child(counterparty_pub, invoice)
|
|
69
71
|
end
|
|
@@ -127,6 +127,7 @@ module BSV
|
|
|
127
127
|
counterparty: nil, privileged: false, privileged_reason: nil,
|
|
128
128
|
seek_permission: true, originator: nil)
|
|
129
129
|
counterparty ||= 'anyone'
|
|
130
|
+
BSV.logger&.debug { "[ProtoWallet] create_signature: protocol=#{protocol_id} key_id=#{key_id.inspect} counterparty=#{counterparty}" }
|
|
130
131
|
priv_key = @key_deriver.derive_private_key(protocol_id, key_id, counterparty)
|
|
131
132
|
|
|
132
133
|
hash = if hash_to_directly_sign
|
|
@@ -156,6 +157,10 @@ module BSV
|
|
|
156
157
|
privileged: false, privileged_reason: nil,
|
|
157
158
|
seek_permission: true, originator: nil)
|
|
158
159
|
counterparty ||= 'self'
|
|
160
|
+
BSV.logger&.debug do
|
|
161
|
+
"[ProtoWallet] verify_signature: protocol=#{protocol_id} key_id=#{key_id.inspect} " \
|
|
162
|
+
"counterparty=#{counterparty} for_self=#{for_self}"
|
|
163
|
+
end
|
|
159
164
|
|
|
160
165
|
pub_key = @key_deriver.derive_public_key(
|
|
161
166
|
protocol_id, key_id, counterparty, for_self: for_self
|
|
@@ -169,6 +174,7 @@ module BSV
|
|
|
169
174
|
|
|
170
175
|
sig = BSV::Primitives::Signature.from_der(bytes_to_string(signature))
|
|
171
176
|
valid = pub_key.verify(hash, sig)
|
|
177
|
+
BSV.logger&.debug { "[ProtoWallet] verify_signature result=#{valid}" }
|
|
172
178
|
|
|
173
179
|
raise InvalidSignatureError unless valid
|
|
174
180
|
|
data/lib/bsv-sdk.rb
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
require_relative 'bsv/version'
|
|
4
4
|
|
|
5
5
|
module BSV
|
|
6
|
+
class << self
|
|
7
|
+
# Optional logger for debug-level instrumentation of txid conversions,
|
|
8
|
+
# BEEF wiring, and merkle path operations.
|
|
9
|
+
#
|
|
10
|
+
# No logger is configured by default — zero overhead when unused.
|
|
11
|
+
# Consumers opt in via:
|
|
12
|
+
#
|
|
13
|
+
# require 'logger'
|
|
14
|
+
# BSV.logger = Logger.new($stdout).tap { |l| l.level = Logger::DEBUG }
|
|
15
|
+
#
|
|
16
|
+
# @return [Logger, nil]
|
|
17
|
+
attr_accessor :logger
|
|
18
|
+
end
|
|
19
|
+
|
|
6
20
|
autoload :Primitives, 'bsv/primitives'
|
|
7
21
|
autoload :Script, 'bsv/script'
|
|
8
22
|
autoload :Transaction, 'bsv/transaction'
|