Я делаю некоторый анализ набора UTXO, считывая данные из базы данных chainstate.
Я следил за документами, предоставленными https://github.com/bitcoin/bitcoin/blob/d4a42334d447cad48fb3996cad0fd5c945b75571/src/coins.h#L19-L34 .
/** 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).
Парсер нормально работал, когда количество UTXO невелико. Однако для следующего tx (с 2501 выходом) это не удалось:
2540b961f4a0b231db3bc5a23608307394eae037d8afd0462e9b794e02f00000
Для ключа 'c' + 2540b961f4a0b231db3bc5a23608307394eae037d8afd0462e9b794e02f00000
значение (деобфускированное) в цепочке выглядит следующим образом:
01907050e140254150443a0c280004...
Где 01
находится версия, которая сообщает, 9070
является nCode
ли это coinbase tx, неизрасходованным vout[0]
, vout[1]
и длиной следующего битового вектора неизрасходованного для vout[2:]
. Глядя на blockchain.info, есть 2501 вывод, поэтому за ними должны следовать (2501 - 2)/8 = 312
байты. Однако разбор 9070
как вариант, удаление последних трех бит и +1 дают мне только 2288 / 8 + 1 = 287
. (Я получил 2288 от (0x90 - 0x80 + 1) * 0x80 + 0x70
, это вариант MSB-128, используемый в протоколе биткойнов.)
Я что-то пропустил здесь? Как именно разбирается варинт?
Вы правы, однако вы не правильно интерпретируете результат. Значение действительно равно 287
, то есть (2288 >> 3) + 1
, однако это означает не то, что битвектор содержит 287 bytes
, а то, что он содержит 287 non-zero bytes
, поэтому при разборе битвектора следует уменьшать счетчик байтов только тогда, когда вы найдете ненулевое значение. Здесь у вас есть кусок кода, который имеет дело с этим ( n
в 287
данном случае):
# 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
Обратите внимание, что это всего лишь фрагмент кода. Недавно я написал полный декодер на Python, вы можете проверить код на github .
час__
час__
CTxOuts
сериализуются? Я понимаю, что большинство из них имеют формуCompressedAmount + 00 + hash160 of pubkey
, но есть много нестандартных транзакций, которые трудно разобрать.Питер Уилле
ср-ги
час__
ср-ги