From 2b4569896236828ae3a1840537cd186bc354c778 Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Sat, 22 Oct 2016 11:38:26 +0900 Subject: [PATCH] Remove Outpoint as a separate object Hopefully this is a little more efficient --- lib/tx.py | 47 ++++++++++++++++++--------------------- server/block_processor.py | 2 +- server/cache.py | 16 ++++++------- 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/lib/tx.py b/lib/tx.py index dfa417c..c45425c 100644 --- a/lib/tx.py +++ b/lib/tx.py @@ -2,11 +2,10 @@ # and warranty status of this software. from collections import namedtuple -import binascii import struct from lib.util import cachedproperty -from lib.hash import double_sha256 +from lib.hash import double_sha256, hash_to_str class Tx(namedtuple("Tx", "version inputs outputs locktime")): @@ -15,17 +14,17 @@ class Tx(namedtuple("Tx", "version inputs outputs locktime")): def is_coinbase(self): return self.inputs[0].is_coinbase -OutPoint = namedtuple("OutPoint", "hash n") + # FIXME: add hash as a cached property? -# prevout is an OutPoint object -class TxInput(namedtuple("TxInput", "prevout script sequence")): +class TxInput(namedtuple("TxInput", "prev_hash prev_idx script sequence")): ZERO = bytes(32) MINUS_1 = 4294967295 @cachedproperty def is_coinbase(self): - return self.prevout == (TxInput.ZERO, TxInput.MINUS_1) + return (self.prev_hash == TxInput.ZERO + and self.prev_idx == TxInput.MINUS_1) @cachedproperty def script_sig_info(self): @@ -34,11 +33,11 @@ class TxInput(namedtuple("TxInput", "prevout script sequence")): return None return Script.parse_script_sig(self.script) - def __repr__(self): - script = binascii.hexlify(self.script).decode("ascii") - prev_hash = binascii.hexlify(self.prevout.hash).decode("ascii") - return ("Input(prevout=({}, {:d}), script={}, sequence={:d})" - .format(prev_hash, self.prevout.n, script, self.sequence)) + def __str__(self): + script = self.script.hex() + prev_hash = hash_to_str(self.prev_hash) + return ("Input({}, {:d}, script={}, sequence={:d})" + .format(prev_hash, self.prev_idx, script, self.sequence)) class TxOutput(namedtuple("TxOutput", "value pk_script")): @@ -56,11 +55,12 @@ class Deserializer(object): self.cursor = 0 def read_tx(self): - version = self.read_le_int32() - inputs = self.read_inputs() - outputs = self.read_outputs() - locktime = self.read_le_uint32() - return Tx(version, inputs, outputs, locktime) + return Tx( + self.read_le_int32(), # version + self.read_inputs(), # inputs + self.read_outputs(), # outputs + self.read_le_uint32() # locktime + ) def read_block(self): tx_hashes = [] @@ -81,15 +81,12 @@ class Deserializer(object): return [self.read_input() for i in range(n)] def read_input(self): - prevout = self.read_outpoint() - script = self.read_varbytes() - sequence = self.read_le_uint32() - return TxInput(prevout, script, sequence) - - def read_outpoint(self): - hash = self.read_nbytes(32) - n = self.read_le_uint32() - return OutPoint(hash, n) + return TxInput( + self.read_nbytes(32), # prev_hash + self.read_le_uint32(), # prev_idx + self.read_varbytes(), # script + self.read_le_uint32() # sequence + ) def read_outputs(self): n = self.read_varint() diff --git a/server/block_processor.py b/server/block_processor.py index 94ca616..35a7f2f 100644 --- a/server/block_processor.py +++ b/server/block_processor.py @@ -439,7 +439,7 @@ class BlockProcessor(LoggedClass): hash168s = cache.add_many(tx_hash, tx_num, tx.outputs) if not tx.is_coinbase: for txin in tx.inputs: - hash168s.add(cache.spend(txin.prevout)) + hash168s.add(cache.spend(txin)) for hash168 in hash168s: self.history[hash168].append(tx_num) diff --git a/server/cache.py b/server/cache.py index 315f1a4..7cf8978 100644 --- a/server/cache.py +++ b/server/cache.py @@ -120,21 +120,21 @@ class UTXOCache(LoggedClass): return hash168s - def spend(self, prevout): + def spend(self, txin): '''Spend a UTXO and return the address spent. If the UTXO is not in the cache it must be on disk. ''' # Fast track is it's in the cache pack = struct.pack - key = prevout.hash + pack('