Исходная информация
Я создаю приложение, которое требует возможности запрашивать любой полный биткойн-узел (из сценария Python с использованием необработанных сокетов tcp), чтобы прочитать значение OP_Return, указанное в следующей транзакции ( https://live.blockcypher.com/btc- testnet/tx/2599dbe540a583ede3512fef9a0f26be718c039ffd4d04d85ff3b339f40e73b1/ )
Что я сделал на сегодняшний день
Мне удалось установить версию + verack, однако я столкнулся с двумя проблемами.
getdata
на нужную транзакцию, Idit не возвращает результат. Я определил, что это связано с тем, что мои первоначальные предположения о том, что getdata возвращает необходимые данные, были неверны, и вместо этого он будет возвращать данные транзакций только для транзакций, все еще находящихся в мемпуле.Это привело меня к моей основной проблеме: я надеялся воспроизвести начальную загрузку блока в моем скрипте Python, начиная с блока, содержащего интересующую меня транзакцию. Однако, когда я делаю/независимо от того, что я, кажется, помещаю getblocks
в getheaders
хэш filter Я получаю дамп из 500 (или 2000) блоков/заголовков. Ниже приведен шестнадцатеричный дамп запросов, которые я делаю (только кадр протокола биткойн):
getblocks 0b110907676574626c6f636b00000000450000002a0af9950100000001000000000000592589e55cda6e8a093998e8356ea770d4aaeb7c0f5439b147d7000000000000017a09017d52db538d7a9ddcc48311866d7e5fdbbbec7d0faad5
getheaders 0b110907676574686561646572730000450000002a0af9950100000001000000000000592589e55cda6e8a093998e8356ea770d4aaeb7c0f5439b147d7000000000000017a09017d52db538d7a9ddcc48311866d7e5fdbbbec7d0faad5
Я ищу следующую помощь:
getdata
сообщение?РЕДАКТИРОВАТЬ (4/5/20) Подразумеваемое требование, которое здесь не было разъяснено, заключалось в том, что нам нужно было сделать это децентрализованным способом, используя блокчейн RPC API или аналогичный.
Я не вижу конечной точки для получения всей транзакции в документации API Blockcypher, поэтому я использовал API blockstream.info:
>https://blockstream.info/testnet/api/tx/2599dbe540a583ede3512fef9a0f26be718c039ffd4d04d85ff3b339f40e73b1
{
"txid":"2599dbe540a583ede3512fef9a0f26be718c039ffd4d04d85ff3b339f40e73b1",
"version":2,
"locktime":0,
"vin":[
{
"txid":"382bda6ee2bac22afd051104af16146436895ecca382a76c2d66535a837254bc",
"vout":1,
"prevout":{
"scriptpubkey":"00144ecdb2867150ff16c7d6e3258adca9ed8bac3ac1",
"scriptpubkey_asm":"OP_0 OP_PUSHBYTES_20 4ecdb2867150ff16c7d6e3258adca9ed8bac3ac1",
"scriptpubkey_type":"v0_p2wpkh",
"scriptpubkey_address":"tb1qfmxm9pn32rl3d37kuvjc4h9fak96cwkpjyyjmk",
"value":2948920
},
"scriptsig":"",
"scriptsig_asm":"",
"witness":[
"304402205e9b17758d1daf2a501a1fabe06bdbf15adaadfcf6ff80c4cfb34176bd988c0c02207450185bde5c20e06270b3b7e681e0042072c6af25fc10c62430df0f04ec5bf201",
"023532fa6b866f37729719a3615ef3a776407048989736ac2b7fafa5678a519df3"
],
"is_coinbase":false,
"sequence":4294967295
}
],
"vout":[
{
"scriptpubkey":"6a0e3132372e302e302e313a38313831",
"scriptpubkey_asm":"OP_RETURN OP_PUSHBYTES_14 3132372e302e302e313a38313831",
"scriptpubkey_type":"op_return",
"value":0
},
{
"scriptpubkey":"a914171f697fe358f7d7238b6128930bb1fa7363b44d87",
"scriptpubkey_asm":"OP_HASH160 OP_PUSHBYTES_20 171f697fe358f7d7238b6128930bb1fa7363b44d OP_EQUAL",
"scriptpubkey_type":"p2sh",
"scriptpubkey_address":"2MuMVAFK2gbTDNVBhLtpZfA4Xi62mWh6bU5",
"value":948920
},
{
"scriptpubkey":"0014af8abd63a00c40ad75e47870b1b0a1ddb2ba7e66",
"scriptpubkey_asm":"OP_0 OP_PUSHBYTES_20 af8abd63a00c40ad75e47870b1b0a1ddb2ba7e66",
"scriptpubkey_type":"v0_p2wpkh",
"scriptpubkey_address":"tb1q479t6caqp3q26a0y0pctrv9pmket5lnx24twcx",
"value":1500000
}
],
"size":248,
"weight":665,
"fee":500000,
"status":{
"confirmed":true,
"block_height":1612110,
"block_hash":"000000000000592589e55cda6e8a093998e8356ea770d4aaeb7c0f5439b147d7",
"block_time":1576024567
}
}
Здесь вы можете видеть, что первый вывод имеет данные 3132372e302e302e313a38313831
, декодирование которых в символы ASCII выглядит как локальный URL:
hex = '3132372e302e302e313a38313831'
decoded = binascii.unhexlify(hex).decode('ascii')
print(decoded)
Отпечатки:127.0.0.1:8181
РЕДАКТИРОВАТЬ:
Чтобы получить интересующую вас транзакцию без использования какого-либо внешнего API, вам нужно будет запустить полный биткойн-узел с опцией txindex=1
. Если эта транзакция отслеживается вашим кошельком, будет достаточно обрезанного узла. Затем вы можете получить информацию о транзакции с помощью этой команды:
>bitcoin-cli getrawtransaction 2599dbe540a583ede3512fef9a0f26be718c039ffd4d04d85ff3b339f40e73b1 true
Вы должны получить что-то очень похожее на ответ из API-интерфейса blockstream, который я вставил выше.
Биткойн-протокол p2p напрямую не разрешает поиск транзакций таким образом. Возможно, некоторая фильтрация Блума минимизирует занимаемую площадь, но реализовать ее все еще относительно сложно.
Серверы Electrum, возможно, являются следующей лучшей вещью — они поддерживают поиск, который вы хотите, но они менее децентрализованы, и если ваше приложение делает непослушные вещи, они могут вступить в сговор и манипулировать только вашими результатами.
Как сделать так, чтобы ответ моего блока или заголовков содержал только 1 элемент запроса вместо 500/5000
Я не думаю, что вы можете ограничить результаты заголовков (для этого вам нужно знать все заголовки). Но как только у вас есть цепочка заголовков, вы можете отправить локатор блоков с start:HASH(n) end:HASH(n+ 1) и вы можете скачать один блок.
Повторная фильтрация Блума, если вы найдете узлы с битом BLOOM_SERVICE, вы можете сообщить им свой фильтр, а данные блока содержат только ваши txs и ложные срабатывания, разрешенные вашим фильтром.
Оказывается, основная проблема с приведенным выше кодом заключалась в том, что порядок следования байтов в python по умолчанию был перепутан с моей шестнадцатеричной полезной нагрузкой. Мне просто нужно было исправить порядок полезной нагрузки. Правильный код можно посмотреть здесь: https://github.com/dummytree/blockchain-botnet-poc/blob/master/MalwareManager.py#L284-L299 .
Кларис
Дмитрий
Кларис
Дмитрий
Питер Уилле
Дмитрий
Дмитрий