2

I am trying to obtain information about a raw transaction in hex before it is broadcasted. This command multiple elements JSON formatted. I'd like a simpler explanation for them:

txid - hash of the transaction itself

hash - hash of the transaction itself. If transaction is non-segwit, txid == hash, otherwise in segwit transactions the transaction hash is different.

version - this is obvious what it is, but how should be interpreted?

size - size of the transaction in bytes

vsize - weighted size for segwit transactions

locktime - lock time of this transaction either in block height either in unix time. OP_CLTV is only determinable from the redeemscript, not from this field.

vin - this subset includes all the inputs being spent.

  • txid - txid of the input being spent.
  • vout - what is this?
  • scriptSig - asm / hex - this includes the signature(s) and redeemScript of this particular input. Is there any difference between asm and hex?
  • sequence - how can this be interpreted? How can one determine if the input is either CSV locked, either replace-able by fee (RBF)?

vout - this subset includes all the outputs of the transaction:

  • value - amount of this output.
  • n - this looks like the number / ordering of outputs?
  • scriptPubKey - script or pubkeyhash of the output
  • reqSigs - how can this be known in advance by the sender, only by having the address?
  • type - how can this be know in advance as well?

Additional questions:

  • How can the amount of each input within the vin subset be determined?
  • How can the scriptSig be validated, like: is the input CLTV or CSV locked? Does the redeemScript (if p2sh) validate to true (e.g. required number of sigs available, other IF/ELSE rules fulfilled)?

3 Answers 3

1

Your post is a bit long, in stack exchange we prefer shotrt, easy to answer questions - see here: https://bitcoin.stackexchange.com/help/how-to-ask

You probably have an example of a JSON interpretation as reference. From where do you have it? As everyone can interpret a raw transaction, I think it is best to reference the original raw transaction from bitcoin.org. This is anambigous. It would look like this (non-segwit, to keep it easy going. Segwit only on demand :-)

VERSION
TX_IN COUNT         (how many input this tx has)
 TX_IN[0...n]
  OutPoint hash     (the previous tx where funds come from)
  OutPoint index    (the n'th TX_IN)
  Script Length     (the length of the following Script Sig)
  Script Sig        (signature)
  Sequence          (a sequence field, originally intended to disable lock-time) 
TX_OUT COUNT        (how many outputs this tx has)
 TX_OUT[0...n]
  Value             (the value in Satoshis)
  PK_Script Length  (length of the following script)
  pk_script         (the script, which defines the condition, under which the funds can be spent)
LOCKTIME            (earliest time or earliest block when that transaction may be added to the block chain)

The assembly of a tx before to be sent was pretty well explained by the answer of @amaclin here.

How can the amount of each input within the vin subset be determined?

The wallet software would need to lookup the values when wanting to spend a new tx. Therefor a reference to a previous tx is required, where v_in is found. If unsufficient for the current spent, then another v_in or even another tx with its v_in will be used (TX_IN count would be increased).

How can the scriptSig be validated, like: is the input CLTV or CSV locked?

I do not understand what you mean by this. Scriptsig and CLTV/CSV are not directly linked to scriptsig. CLTV and CSV both came into the game by BIP-68 and BIP-112. CLTV (as also locktime) are both absolute timelocks, with CSV we talk about relative timelocks. So they define, when a transaction's output can be spent. Maybe worthwhile to lookup in the BIPs. There is also lots in the forum here and in bitcointalk.

Scriptsig (in general) is validated with the hash and the pubkey. Ken Shirrif's blog (link at the bottom) explains very well. Scriptsig proofs, that you had the private key ("you are the rightful owner") to spend this transaction. The privkey signs a hash of the tx, which is followed by the pubkey. There can be more to it, but I want to stay general. Here is an example how you can verify a signature at the unixoide systems shell with openssl (bitcoin always uses hex encoded data to do hashes, and openssl needs a PEM formatted key):

sig=30450221009a29101094b283ae62a6fed68603c554ca3a624b9a78d83e8065edcf97ae231b02202cbed6e796ee6f4caf30edef8f5597a08a6be265d6601ad92283990b55c038fa
pk=03F5D0FB955F95DD6BE6115CE85661DB412EC6A08ABCBFCE7DA0BA8297C6CC0EC4
hash=4eb4dccd727e81315a9ff801c205efc62635471cf8668e42c1c8aebfb51500a3
printf $( echo $hash | sed 's/[[:xdigit:]]\{2\}/\\x&/g' ) > tmp_utx_dsha256.hex
echo "MDYwEAYHKoZIzj0CAQYFK4EEAAoDIgAD9dD7lV+V3WvmEVzoVmHbQS7GoIq8v859oLqCl8bMDsQ=" > cat pubkey.pem
printf $( echo $sig | sed 's/[[:xdigit:]]\{2\}/\\x&/g' ) > tmp_sig.hex
openssl pkeyutl <tmp_utx_dsha256.hex -verify -pubin -inkey pubkey.pem -sigfile tmp_sig.hex

Does the redeemScript (if p2sh) validate to true (e.g. required number of sigs available, other IF/ELSE rules fulfilled)?

The redeemscript is basically a hash of "something". It has the advantage to "hide", what is intended, when the funding transaction is mined into the blockchain. When you create your spending transaction, then the data of your p2sh script is revealed. The common usage is a multisig script. But you can put all type of code into it, which would define the condition, under which funds can be spent (next to multisig, any type of smart contracts, ...). There are limitations to it. The OPCODES, that can be used are explained here. In bitcoin.org are also explanations on p2sh.

I learned all this from 2 additional references: the unbelievably well written book "Mastering Bitcoin" from Andreas, and a very good explanation on transactions by Ken Shirrif.

1

txid - hash of the transaction itself

Indeed. It is the hash of the transaction without witness data included (if any).

hash - hash of the transaction itself. If transaction is non-segwit, txid == hash, otherwise in segwit transactions the transaction hash is different.

Indeed. It is the hash of the transaction with witness data included (if any). The serialization this is commputed over is defined in BIP144.

version - this is obvious what it is, but how should be interpreted?

It reports the contents of the transaction's nVersion field.

Currently there are two transaction version numbers defined:

  • 1: the original version number
  • 2: defined in BIP68. Transactions with this version number (or higher) have their nSequence fields interpreted according to the new rules specified in BIP68.
  • Any other version numbers are non-standard (won't be relayed by common node software on the network), but permitted by to block validity rules. 0 has the same meaning as 1; 3 and higher have the same meaning as 2.

size - size of the transaction in bytes

Indeed. It is the size of the transaction's serialization.

vsize - weighted size for segwit transactions

Indeed. It is the size of the serialization, where witness data is discounted by a factor 4, as specified in BIP141.

locktime - lock time of this transaction either in block height either in unix time. OP_CLTV is only determinable from the redeemscript, not from this field.

Indeed. It reports the value of the transaction's nLocktime field. It is the time or height until which the transaction cannot be included in a block. So for example, a transaction with locktime 700000 can only be included in blocks with height 700001 or higher.

The OP_CHECKLOCKTIMEVERIFY opcode (aka OP_CLTV; defined in BIP65) provides a way to enforce constraints n the nLocktime field of the spending transaction from inside scripts, and thus indirectly on the time when the output can be spent. It is available in all script constructions (bare, P2SH, P2WSH, ...), but would be nonstandard in bare ones.

vin - this subset includes all the inputs being spent.

This is an array containing information about all the transactions' inputs, which are stored in its vin field.

  • txid - txid of the input being spent.

More specificially, it is the hash value of the transaction input's prevout field, which contains the txid of the transaction that created the UTXO being spent by this input.

  • vout - what is this?

It is the n value of the transaction input's prevout field. It reports which index in the creating transaction's vout array is being spent.

  • scriptSig - asm / hex - this includes the signature(s) and redeemScript of this particular input. Is there any difference between asm and hex?

Indeed. The hex value is exactly what is stored in the transaction. The asm value is a more human-readable decoding of that data.

  • sequence - how can this be interpreted? How can one determine if the input is either CSV locked, either replace-able by fee (RBF)?

It is the value of the transaction's nSequence field.

It modern meaning is twofold:

  • Whenever a transaction has nVersion 2 or higher, and the nSequence value is less that 22, the BIP68 rules apply, which puts constraints on how long ago the output being spent must be before this transaction is valid (in height or time). The BIP112 opcode OP_CHECKSEQUENCEVERIFY (aka OP_CSV) provides a means in script to put constraints on the nSequence value (and thus indirectly on the relative time the output can be spent).
  • BIP125 specifies a potential policy (not consensus rule) for nodes about replacement of transactions while in the mempool. Specifically, it permits replacement of any transaction whose nSequence value is not 0xFFFFFFF or 0xFFFFFFFE. This is the case for any transaction input using relative locktime as discussed in the bulletpoint above. Note that modern nodes as of writing do not implement the BIP125 policy rules exactly, though not in a way that makes this description invalid.

vout - this subset includes all the outputs of the transaction:

This is an array containing information about all the transactions' outputs, which are stored in its vout field.

  • value - amount of this output.

Indeed.

  • n - this looks like the number / ordering of outputs?

It is the analogue of the vout field in the inputs. When an input spends a particular UTXO created by this output, it needs to refer to this transactions' txid and n field.

  • scriptPubKey - script or pubkeyhash of the output

It contains the locking script of the UTXO being created, which defined the conditions under which it can be spent. For P2PKH outputs, this is a script that requires a signature by a public key whose hash is a specific value, but it is still a script.

  • reqSigs - how can this be known in advance by the sender, only by having the address?

It can, but only for bare multisig scripts (where the full script is stored in the output directly, and not via a redeemScript), which are deprecated and nonstandard as writing. The reqSigs field is also being deprecated now for that reason. It is just confusing.

  • type - how can this be know in advance as well?

It is the type of output. e.g. it can tell the difference between a P2PKH or P2SH output. It cannot know what the P2SH output's script is, until it gets spent.

  • How can the amount of each input within the vin subset be determined?

It is looked up in the UTXO set database at spending time, using the txid and vout fields reported in the RPC output. Those two unique identify a transaction output (number vout of transaction whose txid is txid), and the UTXO set remembers its amount and scriptPubKey fields.

  • How can the scriptSig be validated, like: is the input CLTV or CSV locked? Does the redeemScript (if p2sh) validate to true (e.g. required number of sigs available, other IF/ELSE rules fulfilled)?

Execution proceeds as follows, roughly:

  • First the scriptSig is executed. The final stack state is remembered. If it fails, the transaction is invalid.
  • Then the scriptPubKey of the output being spent is executed, with the previous final stack state as initial state. This scriptPubKey is looked up in the UTXO database as listed above. So what this effectively does is running the locking script, with the scriptSig as input; if that fails, the transaction is invalid.
  • Then, as a special step, if the scriptPubKey matches the BIP16 (P2SH) template exactly, an additional rule triggers: the final scriptSig element is treated as another script, and executed with all but the final scriptSig element as input.

Similar rules apply to P2WSH (BIP141) and P2TR (BIP341) spends.

0

With bitcoin-core you'd use decoderawtransaction

https://en.bitcoin.it/wiki/Raw_transactions#decoderawtransaction_.3Chex_string.3E

Example with my node

decoderawtransaction 01000000000101502c5d0d5e7e869ff1b40cc1542695fb35830355861f61932645fa1b1a149a5d0e000000171600149a1c78a507689f6f54b847ad1cef1e614ee23f1effffffff01c8f703000000000017a914691ad0b9182c753a26bed191e470b85236b67a878702483045022100817d7d87af9568c025e5dac8bc2b27bdac7181779b81ed5dc8a468f970c33124022059e09b0b5f48516b01ed2262084c8ba1a58a250b3f2e39a69b890f68237e8cb5012103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd00000000



{
  "txid": "1c5cb1487867459952d78624577788723f7d11d8ba39d211e524a9527d683152",
  "hash": "a660d4e8f9f9fc18866a38bac30f25ceef5ecfc8eaf640fc93004b3ea8763d9f",
  "version": 1,
  "size": 216,
  "vsize": 134,
  "weight": 534,
  "locktime": 0,
  "vin": [
    {
      "txid": "5d9a141a1bfa452693611f8655038335fb952654c10cb4f19f867e5e0d5d2c50",
      "vout": 14,
      "scriptSig": {
        "asm": "00149a1c78a507689f6f54b847ad1cef1e614ee23f1e",
        "hex": "1600149a1c78a507689f6f54b847ad1cef1e614ee23f1e"
      },
      "txinwitness": [
        "3045022100817d7d87af9568c025e5dac8bc2b27bdac7181779b81ed5dc8a468f970c33124022059e09b0b5f48516b01ed2262084c8ba1a58a250b3f2e39a69b890f68237e8cb501",
        "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd"
      ],
      "sequence": 4294967295
    }
  ],
  "vout": [
    {
      "value": 0.00260040,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_HASH160 691ad0b9182c753a26bed191e470b85236b67a87 OP_EQUAL",
        "hex": "a914691ad0b9182c753a26bed191e470b85236b67a8787",
        "reqSigs": 1,
        "type": "scripthash",
        "addresses": [
          "3BGkzr6ioLszJjqX2msqXjqDAFdUVtBY2T"
        ]
      }
    }
  ]
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.