Wie funktioniert die Serialisierung in coins.h?

Ich spreche speziell davon:

/** pruned version of CTransaction: only retains metadata and unspent transaction outputs
 *
 * Serialized format:
 * - VARINT(nVersion)
 * - VARINT(nCode)
 * - unspentness bitvector, for vout[2] and further; least significant byte first
 * - the non-spent CTxOuts (via CTxOutCompressor)
 * - VARINT(nHeight)
 *
 * The nCode value consists of:
 * - bit 1: IsCoinBase()
 * - bit 2: vout[0] is not spent
 * - bit 4: vout[1] is not spent
 * - The higher bits encode N, the number of non-zero bytes in the following bitvector.
 *   - In case both bit 2 and bit 4 are unset, they encode N-1, as there must be at
 *     least one non-spent output).
 *
 * Example: 0104835800816115944e077fe7c803cfa57f29b36bf87c1d358bb85e
 *          <><><--------------------------------------------><---->
 *          |  \                  |                             /
 *    version   code             vout[1]                  height
 *
 *    - version = 1
 *    - code = 4 (vout[1] is not spent, and 0 non-zero bytes of bitvector follow)
 *    - unspentness bitvector: as 0 non-zero bytes follow, it has length 0
 *    - vout[1]: 835800816115944e077fe7c803cfa57f29b36bf87c1d35
 *               * 8358: compact amount representation for 60000000000 (600 BTC)
 *               * 00: special txout type pay-to-pubkey-hash
 *               * 816115944e077fe7c803cfa57f29b36bf87c1d35: address uint160
 *    - height = 203998
 *
 *
 * Example: 0109044086ef97d5790061b01caab50f1b8e9c50a5057eb43c2d9563a4eebbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa486af3b
 *          <><><--><--------------------------------------------------><----------------------------------------------><---->
 *         /  \   \                     |                                                           |                     /
 *  version  code  unspentness       vout[4]                                                     vout[16]           height
 *
 *  - version = 1
 *  - code = 9 (coinbase, neither vout[0] or vout[1] are unspent,
 *                2 (1, +1 because both bit 2 and bit 4 are unset) non-zero bitvector bytes follow)
 *  - unspentness bitvector: bits 2 (0x04) and 14 (0x4000) are set, so vout[2+2] and vout[14+2] are unspent
 *  - vout[4]: 86ef97d5790061b01caab50f1b8e9c50a5057eb43c2d9563a4ee
 *             * 86ef97d579: compact amount representation for 234925952 (2.35 BTC)
 *             * 00: special txout type pay-to-pubkey-hash
 *             * 61b01caab50f1b8e9c50a5057eb43c2d9563a4ee: address uint160
 *  - vout[16]: bbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa4
 *              * bbd123: compact amount representation for 110397 (0.001 BTC)
 *              * 00: special txout type pay-to-pubkey-hash
 *              * 8c988f1a4a4de2161e0f50aac7f17e7f9555caa4: address uint160
 *  - height = 120891
 */

Ich verstehe nicht wirklich, wie nCode funktioniert. Nehmen wir das zweite Beispiel:

Das erste Bit wird gesetzt, um anzuzeigen, dass es sich um eine Coinbase-Transaktion handelt. Bisher nCode = 01. vout[0] und vout[1] werden ausgegeben, was bedeutet, dass wir 1 addieren, weil es mindestens 1 nicht ausgegebenen Output gibt. Die Bitmaske ist also 0001 0001, was 0x11 entspricht.

Wir haben also bereits eine Zahl größer als 0x09. Wie zum Teufel wird das nCode = 0x09berechnet?

Antworten (1)

(Anmerkung: Ich werde eine andere Bit-Nummerierung aus dem Kommentar verwenden, die von 0..Bstatt geht 1..2^B, da ich das selbst leichter zu lesen finde)

Die binäre Darstellung von 0x9in funktionellen Gruppen getrennt ist

bit# ...6543 21 0
        ---------
        0001 00 1
  • Bit 0 ist gesetzt, da es sich um eine Coinbase handelt
  • Bit 2 und 1 sind 0, weil vout[0] und vout[1] verbraucht sind
  • Bit 3+ enthält nur die Binärzahl 1. Da Bit 1 und 2 nicht gesetzt sind, codieren diese Bits N-1. N=(9>>3)+1=2. N ist hier die Anzahl der Bytes im nachfolgenden Bitvektor.

Diese beiden folgenden Bytes sind 04und 40, die die Zahl 0x440 codieren, die Zahl, bei der die Bits 2 ( 1<<4=0x04) und 14 ( 1<<14=0x4000) gesetzt sind. Wie im Beispiel beschrieben bedeutet dies, dass vout[2+2]und vout[14+2]nicht ausgegeben werden.

Wie kommst du auf 0x11?

Ich denke, meine erste Verwirrung kommt von der Nummerierung, ich stimme zu, dass Ihre einfacher zu lesen ist.
Allerdings folge ich dir nur so lange, bis du sagst N=(9>>3)+1=2Woher hast du das?
(9>>3) extrahiert die Bits 3+ aus dem eingegebenen nCode unter Verwendung des Shift-right-Operators. Dies ist 1, zu der 1 addiert wird, um 2 zu ergeben.
Ok danke, ich verstehe. Aber jetzt bekomme ich den nächsten Teil nicht. Korrigieren Sie mich, wenn ich falsch liege, aber 2<<4=0x20und 2<<14=0x8000, nein?
Ich sehe immer noch nicht, wie die 0x440Bits 2 und 14 codiert werden. Tut mir leid, ich bin ziemlich neu darin.
Mein Fehler, ich habe den Teil übersprungen, in dem zuerst das niedrigstwertige Byte stand. Jetzt ergibt es für mich Sinn.
Entschuldigung, mein Fehler, Sie müssen 1<<2und verwenden 1<<14. Ich korrigiere meinen Kommentar.