diff --git a/.travis.yml b/.travis.yml index 339b667..9e2b966 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ install: # command to run tests script: - pytest --cov=server --cov=lib --cov=wallet - - pycodestyle server/*.py + - pycodestyle server/*.py lib/*.py # Dont report coverage from nightly after_success: - if [[ $(python3 -V 2>&1) == *"Python 3.6"* ]]; then diff --git a/lib/coins.py b/lib/coins.py index 738d494..dbfdf33 100644 --- a/lib/coins.py +++ b/lib/coins.py @@ -60,7 +60,7 @@ class Coin(object): REORG_LIMIT = 200 # Not sure if these are coin-specific - RPC_URL_REGEX = re.compile('.+@(\[[0-9a-fA-F:]+\]|[^:]+)(:[0-9]+)?') + RPC_URL_REGEX = re.compile('.+@(\\[[0-9a-fA-F:]+\\]|[^:]+)(:[0-9]+)?') VALUE_PER_COIN = 100000000 CHUNK_SIZE = 2016 BASIC_HEADER_SIZE = 80 @@ -260,8 +260,8 @@ class Coin(object): @classmethod def static_header_len(cls, height): '''Given a header height return its length.''' - return cls.static_header_offset(height + 1) \ - - cls.static_header_offset(height) + return (cls.static_header_offset(height + 1) + - cls.static_header_offset(height)) @classmethod def block_header(cls, block, height): @@ -318,7 +318,7 @@ class AuxPowMixin(object): class EquihashMixin(object): STATIC_BLOCK_HEADERS = False - BASIC_HEADER_SIZE = 140 # Excluding Equihash solution + BASIC_HEADER_SIZE = 140 # Excluding Equihash solution DESERIALIZER = lib_tx.DeserializerEquihash @classmethod @@ -383,6 +383,7 @@ class BitcoinMixin(object): '4ff763ae46a2a6c172b3f1b60a8ce26f') RPC_PORT = 8332 + class HOdlcoin(Coin): NAME = "HOdlcoin" SHORTNAME = "HODLC" @@ -573,7 +574,8 @@ class BitcoinCashTestnet(BitcoinTestnetMixin, Coin): PEERS = [ 'electrum-testnet-abc.criptolayer.net s50112', 'bchtestnet.arihanc.com t53001 s53002', - 'ciiattqkgzebpp6jofjbrkhvhwmgnsfoayljdcrve2p3qmkbv3duaoyd.onion t53001 s53002', + 'ciiattqkgzebpp6jofjbrkhvhwmgnsfoayljdcrve2p3qmkbv3duaoyd.onion ' + 't53001 s53002', ] @@ -596,7 +598,7 @@ class BitcoinSegwitRegtest(BitcoinSegwitTestnet): NET = "regtest" GENESIS_HASH = ('0f9188f13cb7b2c71f2a335e3a4fc328' 'bf5beb436012afca590b1a11466e2206') - PEERS= [] + PEERS = [] TX_COUNT = 1 TX_COUNT_HEIGHT = 1 @@ -666,7 +668,7 @@ class LitecoinTestnet(Litecoin): class Viacoin(AuxPowMixin, Coin): - NAME="Viacoin" + NAME = "Viacoin" SHORTNAME = "VIA" NET = "mainnet" P2PKH_VERBYTE = bytes.fromhex("47") @@ -932,6 +934,7 @@ class Zcash(EquihashMixin, Coin): RPC_PORT = 8232 REORG_LIMIT = 800 + class ZcashTestnet(Zcash): SHORTNAME = "TAZ" NET = "testnet" @@ -945,6 +948,7 @@ class ZcashTestnet(Zcash): TX_PER_BLOCK = 2 RPC_PORT = 18232 + class SnowGem(EquihashMixin, Coin): NAME = "SnowGem" SHORTNAME = "SNG" @@ -976,9 +980,11 @@ class SnowGem(EquihashMixin, Coin): 'timestamp': timestamp, 'bits': bits, 'nonce': hash_to_str(header[108:140]), - 'n_solution': base64.b64encode(lib_tx.Deserializer(header, start=140)._read_varbytes()).decode('utf8') + 'n_solution': base64.b64encode(lib_tx.Deserializer( + header, start=140)._read_varbytes()).decode('utf8') } + class BitcoinZ(EquihashMixin, Coin): NAME = "BitcoinZ" SHORTNAME = "BTCZ" @@ -995,6 +1001,7 @@ class BitcoinZ(EquihashMixin, Coin): RPC_PORT = 1979 REORG_LIMIT = 800 + class Hush(EquihashMixin, Coin): NAME = "Hush" SHORTNAME = "HUSH" @@ -1002,8 +1009,8 @@ class Hush(EquihashMixin, Coin): P2PKH_VERBYTE = bytes.fromhex("1CB8") P2SH_VERBYTES = [bytes.fromhex("1CBD")] WIF_BYTE = bytes.fromhex("80") - GENESIS_HASH = ( '0003a67bc26fe564b75daf11186d3606' - '52eb435a35ba3d9d3e7e5d5f8e62dc17') + GENESIS_HASH = ('0003a67bc26fe564b75daf11186d3606' + '52eb435a35ba3d9d3e7e5d5f8e62dc17') DESERIALIZER = lib_tx.DeserializerZcash TX_COUNT = 329196 TX_COUNT_HEIGHT = 68379 @@ -1011,6 +1018,7 @@ class Hush(EquihashMixin, Coin): RPC_PORT = 8822 REORG_LIMIT = 800 + class Zclassic(EquihashMixin, Coin): NAME = "Zclassic" SHORTNAME = "ZCL" @@ -1018,8 +1026,8 @@ class Zclassic(EquihashMixin, Coin): P2PKH_VERBYTE = bytes.fromhex("1CB8") P2SH_VERBYTES = [bytes.fromhex("1CBD")] WIF_BYTE = bytes.fromhex("80") - GENESIS_HASH = ( '0007104ccda289427919efc39dc9e4d4' - '99804b7bebc22df55f8b834301260602') + GENESIS_HASH = ('0007104ccda289427919efc39dc9e4d4' + '99804b7bebc22df55f8b834301260602') DESERIALIZER = lib_tx.DeserializerZcash TX_COUNT = 329196 TX_COUNT_HEIGHT = 68379 @@ -1027,6 +1035,7 @@ class Zclassic(EquihashMixin, Coin): RPC_PORT = 8023 REORG_LIMIT = 800 + class Koto(Coin): NAME = "Koto" SHORTNAME = "KOTO" @@ -1047,6 +1056,7 @@ class Koto(Coin): 'electrum.kotocoin.info s t', ] + class KotoTestnet(Koto): SHORTNAME = "TOKO" NET = "testnet" @@ -1064,6 +1074,7 @@ class KotoTestnet(Koto): 'testnet.kotocoin.info s t', ] + class Komodo(KomodoMixin, EquihashMixin, Coin): NAME = "Komodo" SHORTNAME = "KMD" @@ -1075,6 +1086,7 @@ class Komodo(KomodoMixin, EquihashMixin, Coin): REORG_LIMIT = 800 PEERS = [] + class Monaize(KomodoMixin, EquihashMixin, Coin): NAME = "Monaize" SHORTNAME = "MNZ" @@ -1220,6 +1232,7 @@ class Monacoin(Coin): 'electrum-mona.bitbank.cc s t', ] + class MonacoinTestnet(Monacoin): SHORTNAME = "XMN" NET = "testnet" @@ -1354,15 +1367,16 @@ class CanadaeCoin(AuxPowMixin, Coin): RPC_PORT = 34330 REORG_LIMIT = 1000 + class Denarius(Coin): NAME = "Denarius" SHORTNAME = "DNR" NET = "mainnet" XPUB_VERBYTES = bytes.fromhex("0488b21e") XPRV_VERBYTES = bytes.fromhex("0488ade4") - P2PKH_VERBYTE = bytes.fromhex("1E") #Address starts with a D + P2PKH_VERBYTE = bytes.fromhex("1E") # Address starts with a D P2SH_VERBYTES = [bytes.fromhex("5A")] - WIF_BYTE = bytes.fromhex("9E") #WIF starts with a 6 + WIF_BYTE = bytes.fromhex("9E") # WIF starts with a 6 GENESIS_HASH = ('00000d5dbbda01621cfc16bbc1f9bf32' '64d641a5dbf0de89fd0182c2c4828fcd') DESERIALIZER = lib_tx.DeserializerTxTime @@ -1462,6 +1476,7 @@ class Feathercoin(Coin): 'electrumx-ch-1.feathercoin.ch s t', ] + class UFO(Coin): NAME = "UniformFiscalObject" SHORTNAME = "UFO" @@ -1483,6 +1498,7 @@ class UFO(Coin): 'electrumx1.ufobject.com s t', ] + class Newyorkcoin(AuxPowMixin, Coin): NAME = "Newyorkcoin" SHORTNAME = "NYC" @@ -1498,6 +1514,7 @@ class Newyorkcoin(AuxPowMixin, Coin): TX_PER_BLOCK = 2 REORG_LIMIT = 2000 + class NewyorkcoinTestnet(Newyorkcoin): SHORTNAME = "tNYC" NET = "testnet" @@ -1512,6 +1529,7 @@ class NewyorkcoinTestnet(Newyorkcoin): TX_PER_BLOCK = 2 REORG_LIMIT = 2000 + class Bitcore(BitcoinMixin, Coin): NAME = "Bitcore" SHORTNAME = "BTX" @@ -1540,6 +1558,7 @@ class GameCredits(Coin): RPC_PORT = 40001 REORG_LIMIT = 1000 + class Machinecoin(Coin): NAME = "Machinecoin" SHORTNAME = "MAC" @@ -1558,6 +1577,7 @@ class Machinecoin(Coin): RPC_PORT = 40332 REORG_LIMIT = 800 + class BitcoinAtom(Coin): NAME = "BitcoinAtom" SHORTNAME = "BCA" @@ -1607,10 +1627,13 @@ class Decred(Coin): P2PKH_VERBYTE = bytes('Ds', 'utf-8') P2SH_VERBYTES = [bytes('Dc', 'utf-8')] WIF_BYTE = bytes('Pm', 'utf-8') - GENESIS_HASH = ('298e5cc3d985bfe7f81dc135f360abe089edd4396b86d2de66b0cef42b21d980') + GENESIS_HASH = ('298e5cc3d985bfe7f81dc135f360abe089ed' + 'd4396b86d2de66b0cef42b21d980') DESERIALIZER = lib_tx.DeserializerDecred - ENCODE_CHECK = partial(Base58.encode_check, hash_fn=lib_tx.DeserializerDecred.blake256) - DECODE_CHECK = partial(Base58.decode_check, hash_fn=lib_tx.DeserializerDecred.blake256) + ENCODE_CHECK = partial(Base58.encode_check, + hash_fn=lib_tx.DeserializerDecred.blake256) + DECODE_CHECK = partial(Base58.decode_check, + hash_fn=lib_tx.DeserializerDecred.blake256) HEADER_HASH = lib_tx.DeserializerDecred.blake256 BASIC_HEADER_SIZE = 180 ALLOW_ADVANCING_ERRORS = True @@ -1641,7 +1664,8 @@ class DecredTestnet(Decred): P2PKH_VERBYTE = bytes('Ts', 'utf-8') P2SH_VERBYTES = [bytes('Tc', 'utf-8')] WIF_BYTE = bytes('Pt', 'utf-8') - GENESIS_HASH = ('4261602a9d07d80ad47621a64ba6a07754902e496777edc4ff581946bd7bc29c') + GENESIS_HASH = ('4261602a9d07d80ad47621a64ba6a0' + '7754902e496777edc4ff581946bd7bc29c') TX_COUNT = 3176305 TX_COUNT_HEIGHT = 254198 TX_PER_BLOCK = 1000 @@ -1677,6 +1701,7 @@ class Axe(Dash): import x11_hash return x11_hash.getPoWHash(header) + class Xuez(Coin): NAME = "Xuez" SHORTNAME = "XUEZ" @@ -1688,8 +1713,6 @@ class Xuez(Coin): WIF_BYTE = bytes.fromhex("d4") GENESIS_HASH = ('000000e1febc39965b055e8e0117179a' '4d18e24e7aaa0c69864c4054b4f29445') - - TX_COUNT = 30000 TX_COUNT_HEIGHT = 15000 TX_PER_BLOCK = 1 @@ -1709,7 +1732,7 @@ class Xuez(Coin): import xevan_hash - if version == 1 : + if version == 1: return xevan_hash.getPoWHash(header[:80]) else: return xevan_hash.getPoWHash(header) @@ -1718,7 +1741,7 @@ class Xuez(Coin): def electrum_header(cls, header, height): version, = struct.unpack('= 2: joinsplit_size = self._read_varint() if joinsplit_size > 0: - self.cursor += joinsplit_size * 1802 # JSDescription - self.cursor += 32 # joinSplitPubKey - self.cursor += 64 # joinSplitSig + self.cursor += joinsplit_size * 1802 # JSDescription + self.cursor += 32 # joinSplitPubKey + self.cursor += 64 # joinSplitSig return base_tx @@ -343,11 +343,11 @@ class TxTime(namedtuple("Tx", "version time inputs outputs locktime")): class DeserializerTxTime(Deserializer): def read_tx(self): 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 + self._read_le_int32(), # version + self._read_le_uint32(), # time + self._read_inputs(), # inputs + self._read_outputs(), # outputs + self._read_le_uint32(), # locktime ) @@ -408,7 +408,7 @@ class DeserializerBitcoinAtom(DeserializerSegWit): '''Return the block header bytes''' header_len = static_header_size if height >= self.FORK_BLOCK_HEIGHT: - header_len += 4 # flags + header_len += 4 # flags return self._read_nbytes(header_len) @@ -511,4 +511,4 @@ class DeserializerDecred(Deserializer): locktime, expiry, witness - ), DeserializerDecred.blake256(no_witness_tx) + ), DeserializerDecred.blake256(no_witness_tx) diff --git a/lib/util.py b/lib/util.py index 5577da8..07826f5 100644 --- a/lib/util.py +++ b/lib/util.py @@ -249,7 +249,11 @@ def address_string(address): # See http://stackoverflow.com/questions/2532053/validate-a-hostname-string # Note underscores are valid in domain names, but strictly invalid in host # names. We ignore that distinction. -SEGMENT_REGEX = re.compile("(?!-)[A-Z_\d-]{1,63}(? 255: return False @@ -258,6 +262,7 @@ def is_valid_hostname(hostname): hostname = hostname[:-1] return all(SEGMENT_REGEX.match(x) for x in hostname.split(".")) + def protocol_tuple(s): '''Converts a protocol version number, such as "1.0" to a tuple (1, 0). @@ -267,6 +272,7 @@ def protocol_tuple(s): except Exception: return (0, ) + def version_string(ptuple): '''Convert a version tuple such as (1, 2) to "1.2". There is always at least one dot, so (1, ) becomes "1.0".''' @@ -274,6 +280,7 @@ def version_string(ptuple): ptuple += (0, ) return '.'.join(str(p) for p in ptuple) + def protocol_version(client_req, server_min, server_max): '''Given a client protocol request, return the protocol version to use as a tuple. @@ -298,6 +305,7 @@ def protocol_version(client_req, server_min, server_max): return result + unpack_int32_from = Struct('