Skip to content

Commit

Permalink
Fix encoding and witness type for legacy coinbase transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
Cryp Toon committed Jul 7, 2024
1 parent 150e99e commit 2a40357
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 8 deletions.
2 changes: 1 addition & 1 deletion bitcoinlib/services/bitaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def _parse_transaction(self, tx):
for n, ti in tx['vIn'].items():
if t.coinbase:
t.add_input(prev_txid=ti['txId'], output_n=ti['vOut'], unlocking_script=ti['scriptSig'],
sequence=ti['sequence'], index_n=int(n), value=0)
sequence=ti['sequence'], index_n=int(n), value=0, witness_type=witness_type)
else:
t.add_input(prev_txid=ti['txId'], output_n=ti['vOut'], unlocking_script=ti['scriptSig'],
locking_script=ti['scriptPubKey'], witnesses=ti.get('txInWitness', []),
Expand Down
8 changes: 6 additions & 2 deletions bitcoinlib/services/blockstream.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,20 @@ def _parse_transaction(self, tx):
if tx['status']['confirmed']:
status = 'confirmed'
fee = None if 'fee' not in tx else tx['fee']
witness_type = 'legacy'
if tx['size'] * 4 > tx['weight']:
witness_type = 'segwit'

t = Transaction(locktime=tx['locktime'], version=tx['version'], network=self.network,
fee=fee, size=tx['size'], txid=tx['txid'],
date=None if 'block_time' not in tx['status'] else
datetime.fromtimestamp(tx['status']['block_time'], timezone.utc),
confirmations=confirmations, block_height=block_height, status=status,
coinbase=tx['vin'][0]['is_coinbase'])
coinbase=tx['vin'][0]['is_coinbase'], witness_type=witness_type)
index_n = 0
for ti in tx['vin']:
if tx['vin'][0]['is_coinbase']:
t.add_input(prev_txid=ti['txid'], output_n=ti['vout'], index_n=index_n,
t.add_input(prev_txid=ti['txid'], output_n=ti['vout'], index_n=index_n, witness_type=witness_type,
unlocking_script=ti['scriptsig'], value=0, sequence=ti['sequence'], strict=self.strict)
else:
witnesses = []
Expand Down
9 changes: 5 additions & 4 deletions bitcoinlib/services/mempool.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,17 @@ def _parse_transaction(self, tx):
confirmations = self.latest_block - block_height + 1
tx_date = datetime.fromtimestamp(tx['status']['block_time'], timezone.utc)
status = 'confirmed'
witness_type = 'legacy'
if tx['size'] * 4 > tx['weight']:
witness_type = 'segwit'

t = Transaction(locktime=tx['locktime'], version=tx['version'], network=self.network, block_height=block_height,
fee=tx['fee'], size=tx['size'], txid=tx['txid'], date=tx_date, confirmations=confirmations,
status=status, coinbase=tx['vin'][0]['is_coinbase'])
status=status, coinbase=tx['vin'][0]['is_coinbase'], witness_type=witness_type)
for ti in tx['vin']:
if ti['is_coinbase']:
t.add_input(prev_txid=ti['txid'], output_n=ti['vout'], unlocking_script=ti['scriptsig'], value=0,
sequence=ti['sequence'], strict=self.strict)
sequence=ti['sequence'], strict=self.strict, witness_type=witness_type)
else:
t.add_input(prev_txid=ti['txid'], output_n=ti['vout'],
unlocking_script=ti['scriptsig'], value=ti['prevout']['value'],
Expand All @@ -118,8 +121,6 @@ def _parse_transaction(self, tx):
for to in tx['vout']:
t.add_output(value=to['value'], address=to.get('scriptpubkey_address', ''), spent=None,
lock_script=to['scriptpubkey'], strict=self.strict)
if 'segwit' in [i.witness_type for i in t.inputs] or 'p2sh-segwit' in [i.witness_type for i in t.inputs]:
t.witness_type = 'segwit'
t.update_totals()
return t

Expand Down
3 changes: 2 additions & 1 deletion bitcoinlib/services/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,8 @@ def _parse_db_transaction(db_tx):
if n.ref_txid == b'\00' * 32:
t.coinbase = True
t.add_input(n.ref_txid.hex(), n.ref_index_n, unlocking_script=n.script, address=n.address,
sequence=n.sequence, value=n.value, index_n=n.index_n, witnesses=n.witnesses, strict=False)
sequence=n.sequence, value=n.value, index_n=n.index_n, witnesses=n.witnesses, strict=False,
witness_type=db_tx.witness_type.value)
else:
t.add_output(n.value, n.address, lock_script=n.script, spent=n.spent, output_n=n.index_n,
spending_txid=None if not n.ref_txid else n.ref_txid.hex(),
Expand Down
7 changes: 7 additions & 0 deletions tests/test_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,13 @@ def test_service_gettransaction_coinbase(self):
['block_hash', 'block_height', 'spent', 'spending_txid', 'spending_index_n',
'flag'])

def test_service_gettransaction_coinbase_legacy(self):
srv = ServiceTest(network='bitcoin')
t = srv.gettransaction('fc27565334c7faa7ceeb457dfb5c8ba459e42c1cd8551a99af41f336fc4fd64d')
self.assertEqual(t.inputs[0].prev_txid, b'\0' * 32)
self.assertEqual(t.witness_type, 'legacy')
self.assertEqual(t.inputs[0].encoding, 'base58')

def test_service_gettransaction_segwit_p2wpkh(self):
expected_dict = {
'block_hash': '00000000000000000006e7007407805af2bfb386439e570f5310bb97cdcf0352',
Expand Down

0 comments on commit 2a40357

Please sign in to comment.