From a4e4f80ad7c3d0b8ead1a4a9296c7604f5f6c3b5 Mon Sep 17 00:00:00 2001 From: "John L. Jegutanis" Date: Mon, 1 May 2017 15:46:22 +0200 Subject: [PATCH] Allow custom Daemon and BlockProcessor classes --- lib/coins.py | 38 ++++++++++++++------------------------ server/controller.py | 14 +++++--------- server/mempool.py | 4 ++-- 3 files changed, 21 insertions(+), 35 deletions(-) diff --git a/lib/coins.py b/lib/coins.py index 48b79e5..e23efa8 100644 --- a/lib/coins.py +++ b/lib/coins.py @@ -40,6 +40,8 @@ import lib.util as util from lib.hash import Base58, hash160, double_sha256, hash_to_str from lib.script import ScriptPubKey from lib.tx import Deserializer, DeserializerSegWit, DeserializerAuxPow, DeserializerZcash +from server.block_processor import BlockProcessor +from server.daemon import Daemon Block = namedtuple("Block", "header transactions") @@ -56,12 +58,15 @@ class Coin(object): RPC_URL_REGEX = re.compile('.+@(\[[0-9a-fA-F:]+\]|[^:]+)(:[0-9]+)?') VALUE_PER_COIN = 100000000 CHUNK_SIZE = 2016 + HASHX_LEN = 11 BASIC_HEADER_SIZE = 80 STATIC_BLOCK_HEADERS = True + DESERIALIZER = Deserializer + DAEMON = Daemon + BLOCK_PROCESSOR = BlockProcessor IRC_PREFIX = None IRC_SERVER = "irc.freenode.net" IRC_PORT = 6667 - HASHX_LEN = 11 # Peer discovery PEER_DEFAULT_PORTS = {'t': '50001', 's': '50002'} PEERS = [] @@ -261,8 +266,7 @@ class Coin(object): '''Returns (header, [(deserialized_tx, tx_hash), ...]) given a block and its height.''' header = cls.block_header(block, height) - deserializer = cls.deserializer() - txs = deserializer(block[len(header):]).read_tx_block() + txs = cls.DESERIALIZER(block[len(header):]).read_tx_block() return Block(header, txs) @classmethod @@ -289,15 +293,13 @@ class Coin(object): 'nonce': nonce, } - @classmethod - def deserializer(cls): - return Deserializer class CoinAuxPow(Coin): # Set NAME and NET to avoid exception in Coin::lookup_coin_class NAME = '' NET = '' STATIC_BLOCK_HEADERS = False + DESERIALIZER = DeserializerAuxPow @classmethod def header_hash(cls, header): @@ -307,7 +309,7 @@ class CoinAuxPow(Coin): @classmethod def block_header(cls, block, height): '''Return the AuxPow block header bytes''' - block = DeserializerAuxPow(block) + block = cls.DESERIALIZER(block) return block.read_header(height, cls.BASIC_HEADER_SIZE) @@ -382,10 +384,7 @@ class BitcoinTestnetSegWit(BitcoinTestnet): bitcoind on testnet, you must use this class as your "COIN". ''' NET = "testnet-segwit" - - @classmethod - def deserializer(cls): - return DeserializerSegWit + DESERIALIZER = DeserializerSegWit class BitcoinNolnet(Bitcoin): @@ -417,6 +416,7 @@ class Litecoin(Coin): WIF_BYTE = bytes.fromhex("b0") GENESIS_HASH = ('12a765e31ffd4059bada1e25190f6e98' 'c99d9714d334efa41a195a7e7e04bfe2') + DESERIALIZER = DeserializerSegWit TX_COUNT = 8908766 TX_COUNT_HEIGHT = 1105256 TX_PER_BLOCK = 10 @@ -433,10 +433,6 @@ class Litecoin(Coin): 'eywr5eubdbbe2laq.onion s50008 t50007', ] - @classmethod - def deserializer(cls): - return DeserializerSegWit - class LitecoinTestnet(Litecoin): SHORTNAME = "XLT" @@ -505,10 +501,7 @@ class ViacoinTestnet(Viacoin): class ViacoinTestnetSegWit(ViacoinTestnet): NET = "testnet-segwit" - - @classmethod - def deserializer(cls): - return DeserializerSegWit + DESERIALIZER = DeserializerSegWit # Source: namecoin.org @@ -756,6 +749,7 @@ class Zcash(Coin): 'd06b4a8a5c453883c000b031973dce08') STATIC_BLOCK_HEADERS = False BASIC_HEADER_SIZE = 140 # Excluding Equihash solution + DESERIALIZER = DeserializerZcash TX_COUNT = 329196 TX_COUNT_HEIGHT = 68379 TX_PER_BLOCK = 5 @@ -782,13 +776,9 @@ class Zcash(Coin): @classmethod def block_header(cls, block, height): '''Return the block header bytes''' - block = DeserializerZcash(block) + block = cls.DESERIALIZER(block) return block.read_header(height, cls.BASIC_HEADER_SIZE) - @classmethod - def deserializer(cls): - return DeserializerZcash - class Einsteinium(Coin): NAME = "Einsteinium" diff --git a/server/controller.py b/server/controller.py index 783353a..ad0b46c 100644 --- a/server/controller.py +++ b/server/controller.py @@ -9,10 +9,8 @@ import asyncio import json import os import ssl -import random import time import traceback -import warnings from bisect import bisect_left from collections import defaultdict from concurrent.futures import ThreadPoolExecutor @@ -20,12 +18,11 @@ from functools import partial import pylru -from lib.jsonrpc import JSONRPC, JSONSessionBase, RPCError +from lib.jsonrpc import JSONSessionBase, RPCError from lib.hash import double_sha256, hash_to_str, hex_str_to_hash from lib.peer import Peer import lib.util as util -from server.block_processor import BlockProcessor -from server.daemon import Daemon, DaemonError +from server.daemon import DaemonError from server.mempool import MemPool from server.peers import PeerManager from server.session import LocalRPC, ElectrumX @@ -50,8 +47,8 @@ class Controller(util.LoggedClass): self.loop.set_default_executor(self.executor) self.start_time = time.time() self.coin = env.coin - self.daemon = Daemon(env.coin.daemon_urls(env.daemon_url)) - self.bp = BlockProcessor(env, self, self.daemon) + self.daemon = self.coin.DAEMON(env.coin.daemon_urls(env.daemon_url)) + self.bp = self.coin.BLOCK_PROCESSOR(env, self, self.daemon) self.mempool = MemPool(self.bp, self) self.peer_mgr = PeerManager(env, self) self.env = env @@ -864,8 +861,7 @@ class Controller(util.LoggedClass): if not raw_tx: return None raw_tx = bytes.fromhex(raw_tx) - deserializer = self.coin.deserializer() - tx, tx_hash = deserializer(raw_tx).read_tx() + tx, tx_hash = self.coin.DESERIALIZER(raw_tx).read_tx() if index >= len(tx.outputs): return None return self.coin.address_from_script(tx.outputs[index].pk_script) diff --git a/server/mempool.py b/server/mempool.py index c7843ba..0a6c27b 100644 --- a/server/mempool.py +++ b/server/mempool.py @@ -198,7 +198,7 @@ class MemPool(util.LoggedClass): not depend on the result remaining the same are fine. ''' script_hashX = self.coin.hashX_from_script - deserializer = self.coin.deserializer() + deserializer = self.coin.DESERIALIZER db_utxo_lookup = self.db.db_utxo_lookup txs = self.txs @@ -270,7 +270,7 @@ class MemPool(util.LoggedClass): if hashX not in self.hashXs: return [] - deserializer = self.coin.deserializer() + deserializer = self.coin.DESERIALIZER hex_hashes = self.hashXs[hashX] raw_txs = await self.daemon.getrawtransactions(hex_hashes) result = []