Analysieren Sie UTXO einer Transaktion von Chainstate

Ich mache eine Analyse des UTXO-Sets, indem ich aus der Chainstate-Datenbank lese.

Ich habe die Dokumente von https://github.com/bitcoin/bitcoin/blob/d4a42334d447cad48fb3996cad0fd5c945b75571/src/coins.h#L19-L34 befolgt

/** 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).

Der Parser hat gut funktioniert, wenn die Anzahl der UTXO klein ist. Für den folgenden TX (mit 2501 Ausgängen) ist dies jedoch fehlgeschlagen:

2540b961f4a0b231db3bc5a23608307394eae037d8afd0462e9b794e02f00000

Für den Schlüssel 'c' + 2540b961f4a0b231db3bc5a23608307394eae037d8afd0462e9b794e02f00000sieht der (deobfuskierte) Wert in Chainstate so aus:

01907050e140254150443a0c280004...

Wo 01ist die Version, 9070ist die , die angibt, nCodeob es sich um einen Coinbase-TX handelt, die Unverbrauchtheit von vout[0], vout[1], und die Länge des folgenden Unverbrauchtheits-Bitvektors für vout[2:]. Wenn Sie sich blockchain.info ansehen, gibt es 2501 Ausgaben, also sollten (2501 - 2)/8 = 312Bytes folgen. Das Parsen 9070als Varint, das Entfernen der letzten Bits und +1 geben mir jedoch nur 2288 / 8 + 1 = 287. (Ich habe 2288 von (0x90 - 0x80 + 1) * 0x80 + 0x70erhalten, was die MSB-128-Variante ist, die im Bitcoin-Protokoll verwendet wird.)

Habe ich hier etwas verpasst? Wie genau analysiert man die Variante?

Antworten (1)

Sie haben Recht, interpretieren das Ergebnis jedoch nicht richtig. Der Wert ist tatsächlich 287, das heißt (2288 >> 3) + 1, aber das bedeutet nicht, dass der Bitvektor enthält 287 bytes, sondern dass er enthält 287 non-zero bytes, also sollten Sie beim Analysieren des Bitvektors den Bytezähler nur dann verringern, wenn Sie einen Wert ungleich Null finden. Hier haben Sie einen Code, der sich damit befasst ( nist 287in diesem Fall):

# If n is set, the encoded value contains a bitvector. The following bytes are parsed until n non-zero bytes have
# been extracted. (If a 00 is found, the parsing continues but n is not decreased)
if n > 0:
    bitvector = ""
    while n:
        data = utxo[offset:offset+2]
        if data != "00":
            n -= 1
        bitvector += data
        offset += 2

Beachten Sie, dass dies nur ein Fragment des Codes ist. Ich habe kürzlich einen vollständigen Decoder in Python codiert, Sie können den Code auf github überprüfen .

Hm, das macht Sinn. Ich habe viele Fragen und Antworten von Ihnen zu diesem Thema gelesen. Vielen Dank!
Darf ich auch fragen, wie CTxOutsserialisiert werden? Ich verstehe, dass die meisten davon die Form CompressedAmount + 00 + hash160 of pubkeyhaben, aber es gibt viele nicht standardmäßige Transaktionen, die schwer zu analysieren sind.
Es ist auch Teil des Codes, den ich in der Antwort verlinkt habe. Lassen Sie mich die Antwort um diesen Teil des Codes erweitern (überprüfen Sie die Kommentare).
Genau, da ist es.