You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In short, every transaction for wallet payments looks like this:
VERSION
# of Inputs
List of INPUTs
(note: these vary wildly between Tx types)
# of Outputs
List of OUTPUTs
LOCKTIME
(only for hashing) SIGHASH_TYPE
Types of Types
Type
Desc
VarInt
"Compressed" (1-9 byte) Integers. The first byte is either 0-252 (1 byte), 253=3-, 254=5-, or 255=9- bytes
Uint32LE
Fixed-width ints written in CPU-order (Little-Endian) rather than Network/Storage-order (Big-Endian)0x01000000 is 1
ASN.1
Like JSON (or XML) of the stone age binary type encoding for ECDSA
ASN.1BigInts
Padded with leading 0x00 if the first byte is >= 0x80, unless the number is negative
OP_ codes
Stack-based Virtual CPU commands for the network nodes
PubKeyHash (PKH)
20-byte (0x14) RIPEMD160 hash of SHA256 hash of ECDSA Public Key X value
Public Key X (& Y)
"Compressed" Public Keys have a 1-byte prefix (0x02 or 0x03, indicating quadrant of the graph, since the X value indicates two possible Y values) and are 32-byte BigInts (possibly 33 with padding)
Signature R & S
ECDSA Signatures have R (32-byte) and S (32-byte) components calculated from the Data, Private Key, and K (seeded, possibly random) values
Byte by Byte
Here's a look at each representation of a TX, byte by byte:
"Raw" Tx
Overview
VERSION
Number of Inputs (VarInt)
List of neutered INPUTS
Previous Output TX ID (256-bit, reversed)
Previous Output Index (32-bit, LE)
0x00 (Script is not included, therefore Size is 0)
There are 3 different byte structures for the same basic transaction:
The "Raw" Tx
This is just inputs (tx ids and indexes from previous outputs) and outputs.
It's pretty much useless. I have no idea why you'd ever want this.
The "Ready-to-Hash" (Signable) Tx
There is one "Ready-to-Hash" Tx (Signable Tx) for each input (even if from the same address)
These are generated in order to creating unique Tx Hashes and verify signatures
The "Ready-to-Broadcast" (Spendable) Tx
These contain enough information to lookup what is needed to reconstruct the Tx Hashes from the info that exists in the blockchain indexes. These have a Tx ID.
Raw Tx (Useless)
There's nothing interesting you can do with these other than pass unit tests.
This format cannot be used to sign or broadcast. It lacks the necessary information to construct either of the useful Tx types.
That said..., here's what a Raw TX looks like, in bytes:
01 00 00 00 # Version Number (32-bit, Little-Endian)# INPUTS SECTION
01 # Number of Inputs (VarInt)# Input 1 of 1
a2bda7b7 # Previous TX ID (256-bit, reversed)
e967346f
cf189cee
2563b084
6d7bec06
bb6db611
9054add1
875bd377
00 00 00 00 # Previous Output Index (32-bit, LE)
00 # Signature Script Size (VarInt)
ffffffff # Sequence Number (always ffffffff)# OUTPUTS SECTION
01 # Number of Outputs (VarInt)# Output 1 of 1
20f1610b00000000 # Output Value / Satoshis (64-bit, LE)
19 # Lock Script Size (25 bytes)
76a9 # OP_DUP, OP_HASH160
14 # PubKeyHash (PKH) Size (20 bytes)
f93af105187d21ed6adf # PubKeyHash
a5d71bfada7d7324e53c
88ac # OP_EQUALVERIFY, OP_CHECKSIG
00000000 # Lock Time
Signable Tx
As stated above, a Raw Tx is useless. It's like an idiot-savant's version of JSON.
The signable TX is similar (example forthcoming), but:
sigScript (and its size) is replaced by the previous transaction's output's lock Script (rather than being 0-length, as in the raw)
The SigHashType (0x01) must be appended as a 32-bit LittleEndian
The double-sha256sum is taken and then reversed
Note: this example was added in haste and may not be perfectly correct. TODO make it perfect!
# version (int32)
01 00 00 00
# number of outputs as inputs (varint)
01
# output at index 0# byte-reversed txid of input's previous output
a2bda7b7e967346fcf189cee2563b0846d7bec06bb6db6119054add1875bd377
# index of input's previous output
00 00 00 00 # prev vout index# size of signature script (actually previous output lock script)
19
# previous output's lock script (TODO use the real one from the tx)
76a9
14
f93af105187d21ed6adfa5d71bfada7d7324e53c
88ac
# sequence of this input
ffffffff
# number of outputs
01
# output at index 0# satoshis (reverse byte order)
20 f1 61 0b 00 00 00 00
# varint size of this output's pubkeyhash script
19
# some op codes
76 a9
# decimal 20, the size of the pubkeyhash
14
# the pubkeyhash (no magic byte or checksum)
f93af105187d21ed6adfa5d71bfada7d7324e53c
# more op codes
88 ac
# locktime
00000000
# version (int32)
01 00 00 00
# number of outputs as inputs (varint)
01
# output at index 0
# byte-reversed txid of input's previous output
a2bda7b7e967346fcf189cee2563b0846d7bec06bb6db6119054add1875bd377
# index of input's previous output
00 00 00 00 # prev vout index
# size of signature script (106 decimal)
- 00+ 6a+ # size of signature + sighashtype (71 in decimal)+ 47+ # ASN.1 Sequence + Size+ 30 44+ # ASN.1 Bytes + Len+ 02 20+ # Signature R value+ 528e92bc890b362efcab0ab1af0f9427d501909be59fe22dbdb4c26eac174181+ # ASN.1 Bytes + Len+ 02 20+ # Signature S Value + 6eb9c83360ad46c9f17be32ea15a08d2765a934e08ce6f2578b3379bbfa03afd+ # SigHashType+ 01+ # Varint PubKey Len (33)+ 21+ # Full Public Key (first byte is quadrant)+ 02 4451fc7d9e271fab77265bd0292fc274ee231e7ecc076bf6269999c0cbbf9f90
# sequence of this input
ffffffff
# number of outputs
01
# output at index 0
# satoshis (reverse byte order)
20 f1 61 0b 00 00 00 00
# varint size of this output's pubkeyhash script
19
# some op codes
76 a9
# decimal 20, the size of the pubkeyhash
14
# the pubkeyhash (no magic byte or checksum)
f93af105187d21ed6adfa5d71bfada7d7324e53c
# more op codes
88 ac
# locktime
00000000
The text was updated successfully, but these errors were encountered:
This is to help you
This project is cryptocurrency-agnostic (BTC, BSV, BCH, DASH, DOGE, etc).
Although this module was written for Dash, the examples come from https://bitcointalk.org/index.php?topic=651344.0.
Table of Contents
Basic Anatomy of a Transaction
In short, every transaction for wallet payments looks like this:
VERSION
#
of InputsINPUT
s(note: these vary wildly between Tx types)
#
of OutputsOUTPUT
sLOCKTIME
SIGHASH_TYPE
Types of Types
VarInt
0x01000000
is 1ASN.1
ASN.1
BigInt
s0x00
if the first byte is >=0x80
, unless the number is negativeOP_
codesByte by Byte
Here's a look at each representation of a TX, byte by byte:
"Raw" Tx
Overview
0xffffffff
)Example
Decoded
"Hashable" Tx
0xffffffff
)"Signed" (Ready-to-Broadcast) Tx
106 to 109, varies due to BigInt padding
0xffffffff
)Amalgam (all 3 types together)
0xffffffff
)Types of Transactions (in Bytes)
There are 3 different byte structures for the same basic transaction:
This is just inputs (tx ids and indexes from previous outputs) and outputs.
It's pretty much useless. I have no idea why you'd ever want this.
There is one "Ready-to-Hash" Tx (Signable Tx) for each input (even if from the same address)
These are generated in order to creating unique Tx Hashes and verify signatures
These contain enough information to lookup what is needed to reconstruct the Tx Hashes from the info that exists in the blockchain indexes. These have a Tx ID.
Raw Tx (Useless)
There's nothing interesting you can do with these other than pass unit tests.
This format cannot be used to sign or broadcast. It lacks the necessary information to construct either of the useful Tx types.
That said..., here's what a Raw TX looks like, in bytes:
If we break that down cleanly into 4 sections:
Signable Tx
As stated above, a Raw Tx is useless. It's like an idiot-savant's version of JSON.
The signable TX is similar (example forthcoming), but:
sigScript
(and its size) is replaced by the previous transaction's output's lock Script (rather than being 0-length, as in the raw)0x01
) must be appended as a 32-bit LittleEndianNote: this example was added in haste and may not be perfectly correct. TODO make it perfect!
A Signed Tx
The signed transaction will look like this:
Which can be broken down like this:
The text was updated successfully, but these errors were encountered: