Verification
To verify the output, you can use the following code. Put the fields that you get in the required format, and match the serialized transaction that comes as the output.
Below is the Python program to verify the serialized transaction:
import hashlib
import struct
import json
def serialize_tx(transaction):
serialized = b""
# Version
serialized += struct.pack("<L", transaction["version"])
# Input count
serialized += encode_varint(len(transaction["vin"]))
for inp in transaction["vin"]:
# TXID in little-endian format
txid_bytes = bytes.fromhex(inp["txid"])[::-1]
serialized += txid_bytes
# Output index
serialized += struct.pack("<L", inp["vout"])
# ScriptSig
scriptsig_bytes = bytes.fromhex(inp.get("scriptsig", ""))
# Script length
serialized += encode_varint(len(scriptsig_bytes))
serialized += scriptsig_bytes
# Sequence
serialized += struct.pack("<L", inp["sequence"])
# Output count
serialized += encode_varint(len(transaction["vout"]))
for out in transaction["vout"]:
# Output value
serialized += struct.pack("<Q", out["value"])
# ScriptPubKey
scriptpubkey_bytes = bytes.fromhex(out["scriptpubkey"])
# ScriptPubKey size
serialized += encode_varint(len(scriptpubkey_bytes))
serialized += scriptpubkey_bytes
# Locktime
serialized += struct.pack("<L", transaction["locktime"])
txid = hashlib.sha256(hashlib.sha256(serialized).digest()).digest()[::-1].hex()
return serialized
def compact_size(value):
if value < 0xFD:
return value.to_bytes(1, "little")
elif value <= 0xFFFF:
return b"\xfd" + value.to_bytes(2, "little")
elif value <= 0xFFFFFFFF:
return b"\xfe" + value.to_bytes(4, "little")
else:
return b"\xff" + value.to_bytes(8, "little")
def encode_varint(n):
if n < 0xFD:
return struct.pack("<B", n)
elif n <= 0xFFFF:
return b"\xfd" + struct.pack("<H", n)
elif n <= 0xFFFFFFFF:
return b"\xfe" + struct.pack("<I", n)
else:
return b"\xff" + struct.pack("<Q", n)
# Example transaction
transaction = {
"version": 1,
"locktime": 0,
"vin": [
{
"txid": "3b239ad258a308129049df85c03f97bd4f57b99825174ad2a50509a08ec2a2b9",
"vout": 0,
"prevout": {
"scriptpubkey": "a914423877331b30a905240c7e1f2adee4ebaa47c5f687",
"scriptpubkey_asm": "OP_HASH160 OP_PUSHBYTES_20 423877331b30a905240c7e1f2adee4ebaa47c5f6 OP_EQUAL",
"scriptpubkey_type": "p2sh",
"scriptpubkey_address": "37jAAWEdJ9D9mXybRobcveioxSkt7Lkwog",
"value": 2504928
},
"scriptsig": "16001415ff0337937ecadd10ce56ffdfd4674817613223",
"scriptsig_asm": "OP_PUSHBYTES_22 001415ff0337937ecadd10ce56ffdfd4674817613223",
"witness": [
"3044022037656a38eff538cb3ccdcd4f47ca80118bcfd60414363b7bc08b1469adedece902206f182c48452cf2b6e6897b03354ed32d0357fc3607f5089b509fef17c498a5cd01",
"035658f6dd92339165f76caff02f63316433c4b68a247d40b1b323fb1690279e42"
],
"is_coinbase": False,
"sequence": 4294967280,
"inner_redeemscript_asm": "OP_0 OP_PUSHBYTES_20 15ff0337937ecadd10ce56ffdfd4674817613223"
},
{
"txid": "4f382663a4491570c2e01a4a5ae4cfcd3b11b52ed2124947816dba9f09e71584",
"vout": 1,
"prevout": {
"scriptpubkey": "a914423877331b30a905240c7e1f2adee4ebaa47c5f687",
"scriptpubkey_asm": "OP_HASH160 OP_PUSHBYTES_20 423877331b30a905240c7e1f2adee4ebaa47c5f6 OP_EQUAL",
"scriptpubkey_type": "p2sh",
"scriptpubkey_address": "37jAAWEdJ9D9mXybRobcveioxSkt7Lkwog",
"value": 58711992
},
"scriptsig": "16001415ff0337937ecadd10ce56ffdfd4674817613223",
"scriptsig_asm": "OP_PUSHBYTES_22 001415ff0337937ecadd10ce56ffdfd4674817613223",
"witness": [
"3044022040a303cd51c50bdf296e89661f8bb3ea411d639c5149cab461a63855d5bf97c502207ac0ce4133e22daba97abc5d65f219c49cea1959247ec398c9c6eaceb4fcd9d801",
"035658f6dd92339165f76caff02f63316433c4b68a247d40b1b323fb1690279e42"
],
"is_coinbase": False,
"sequence": 4294967280,
"inner_redeemscript_asm": "OP_0 OP_PUSHBYTES_20 15ff0337937ecadd10ce56ffdfd4674817613223"
}
],
"vout": [
{
"scriptpubkey": "76a91471a3d2f54b0917dc9d2c877b2861ac52967dec7f88ac",
"scriptpubkey_asm": "OP_DUP OP_HASH160 OP_PUSHBYTES_20 71a3d2f54b0917dc9d2c877b2861ac52967dec7f OP_EQUALVERIFY OP_CHECKSIG",
"scriptpubkey_type": "p2pkh",
"scriptpubkey_address": "1BMscNZbFKdUDYi3bnF5XEmkWT3WPmRBDJ",
"value": 28278016
},
{
"scriptpubkey": "a914423877331b30a905240c7e1f2adee4ebaa47c5f687",
"scriptpubkey_asm": "OP_HASH160 OP_PUSHBYTES_20 423877331b30a905240c7e1f2adee4ebaa47c5f6 OP_EQUAL",
"scriptpubkey_type": "p2sh",
"scriptpubkey_address": "37jAAWEdJ9D9mXybRobcveioxSkt7Lkwog",
"value": 32928544
}
]
}
Serialized=serialize_tx(transaction)
print("Serialized Transaction : ", Serialized.hex())
txid = hashlib.sha256(hashlib.sha256(serialize_tx(transaction)).digest()).digest()[::-1].hex()
print("TXID of transaction : ", txid)
Output:
The output is the same serialized transaction that we took in the beginning to deserialize.
How to Decode Input Data from a Transaction?
When transactions are transmitted over the network or exchanged between applications, they are serialized. Serialization is most commonly used for encoding data structures for transmission over a network or for storage in a file. The serialization format of a transaction output is shown in Transaction output serialization. This article focuses on discussing steps to decode input data from a transaction.
Table of Content
- What is Serialization?
- Raw Bitcoin Transaction
- Format of Various Fields in Serialized Transaction
- Decoding the Transaction
- Detailed Explanation
- Verification
- Conclusion