From 1e9a65dccb33d8f115fc834cc9ab5ec7e9b81645 Mon Sep 17 00:00:00 2001 From: "John L. Jegutanis" Date: Sat, 10 Jun 2017 19:41:44 +0300 Subject: [PATCH] Handle legacy daemon RPCs Add support for daemons that don't have the new 'getblock' RPC call that returns the block in hex, the workaround is to manually recreate the block bytes. The recreated block bytes may not be the exact ones as in the underlying blockchain but it is good enough for our indexing purposes. --- lib/tx.py | 31 ++++++++++++++++++++---- lib/util.py | 15 ++++++++++++ server/daemon.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 5 deletions(-) diff --git a/lib/tx.py b/lib/tx.py index 23aaea6..7ed30ba 100644 --- a/lib/tx.py +++ b/lib/tx.py @@ -123,6 +123,11 @@ class Deserializer(object): self._read_varbytes(), # pk_script ) + def _read_byte(self): + cursor = self.cursor + self.cursor += 1 + return self.binary[cursor] + def _read_nbytes(self, n): cursor = self.cursor self.cursor = end = cursor + n @@ -182,11 +187,6 @@ class DeserializerSegWit(Deserializer): # https://bitcoincore.org/en/segwit_wallet_dev/#transaction-serialization - def _read_byte(self): - cursor = self.cursor - self.cursor += 1 - return self.binary[cursor] - def _read_witness(self, fields): read_witness_field = self._read_witness_field return [read_witness_field() for i in range(fields)] @@ -290,3 +290,24 @@ class DeserializerZcash(Deserializer): self.cursor += 32 # joinSplitPubKey self.cursor += 64 # joinSplitSig return base_tx, double_sha256(self.binary[start:self.cursor]) + + +class TxTime(namedtuple("Tx", "version time inputs outputs locktime")): + '''Class representing transaction that has a time field.''' + + @cachedproperty + def is_coinbase(self): + return self.inputs[0].is_coinbase + + +class DeserializerTxTime(Deserializer): + def read_tx(self): + start = self.cursor + + return TxTime( + self._read_le_int32(), # version + self._read_le_uint32(), # time + self._read_inputs(), # inputs + self._read_outputs(), # outputs + self._read_le_uint32(), # locktime + ), double_sha256(self.binary[start:self.cursor]) diff --git a/lib/util.py b/lib/util.py index 78006b9..2c09127 100644 --- a/lib/util.py +++ b/lib/util.py @@ -34,6 +34,7 @@ import logging import re import sys from collections import Container, Mapping +from struct import pack class LoggedClass(object): @@ -156,6 +157,20 @@ def int_to_bytes(value): return value.to_bytes((value.bit_length() + 7) // 8, 'big') +def int_to_varint(value): + '''Converts an integer to a Bitcoin-like varint bytes''' + if value < 0: + raise Exception("attempt to write size < 0") + elif value < 253: + return pack(' 0: + transactions = await self.getrawtransactions(b.get('tx'), False) + + raw_block = header + num_txs = len(transactions) + if num_txs > 0: + raw_block += util.int_to_varint(num_txs) + raw_block += b''.join(transactions) + else: + raw_block += b'\x00' + + return raw_block + + def timestamp_safe(self, t): + return t if isinstance(t, int) else timegm(strptime(t, "%Y-%m-%d %H:%M:%S %Z"))