diff --git a/lib/coins.py b/lib/coins.py index ed290e5..ee535d6 100644 --- a/lib/coins.py +++ b/lib/coins.py @@ -1,4 +1,5 @@ # Copyright (c) 2016-2017, Neil Booth +# Copyright (c) 2017, the ElectrumX authors # # All rights reserved. # @@ -29,18 +30,15 @@ Anything coin-specific should go in this file and be subclassed where necessary for appropriate handling. ''' -from decimal import Decimal -from functools import partial -from hashlib import sha256 -import inspect import re import struct -import sys +from decimal import Decimal +from hashlib import sha256 -from lib.hash import Base58, hash160, ripemd160, double_sha256, hash_to_str +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 -import lib.util as util class CoinError(Exception): @@ -156,7 +154,7 @@ class Coin(object): def P2PKH_address_from_hash160(cls, hash160): '''Return a P2PKH address given a public key.''' assert len(hash160) == 20 - return Base58.encode_check(bytes([cls.P2PKH_VERBYTE]) + hash160) + return Base58.encode_check(cls.P2PKH_VERBYTE + hash160) @classmethod def P2PKH_address_from_pubkey(cls, pubkey): @@ -167,7 +165,7 @@ class Coin(object): def P2SH_address_from_hash160(cls, hash160): '''Return a coin address given a hash160.''' assert len(hash160) == 20 - return Base58.encode_check(bytes([cls.P2SH_VERBYTE]) + hash160) + return Base58.encode_check(cls.P2SH_VERBYTE + hash160) @classmethod def multisig_address(cls, m, pubkeys): @@ -202,10 +200,11 @@ class Coin(object): ''' raw = Base58.decode_check(address) - # Require version byte plus hash160. + # Require version byte(s) plus hash160. verbyte = -1 - if len(raw) == 21: - verbyte, hash_bytes = raw[0], raw[1:] + verlen = len(raw) - 20 + if verlen > 0: + verbyte, hash_bytes = raw[0:verlen], raw[verlen:] if verbyte == cls.P2PKH_VERBYTE: return ScriptPubKey.P2PKH_script(hash_bytes) @@ -215,9 +214,9 @@ class Coin(object): raise CoinError('invalid address: {}'.format(address)) @classmethod - def prvkey_WIF(privkey_bytes, compressed): + def prvkey_WIF(cls, privkey_bytes, compressed): '''Return the private key encoded in Wallet Import Format.''' - payload = bytearray([cls.WIF_BYTE]) + privkey_bytes + payload = bytearray(cls.WIF_BYTE) + privkey_bytes if compressed: payload.append(0x01) return Base58.encode_check(payload) @@ -292,9 +291,9 @@ class Bitcoin(Coin): NET = "mainnet" XPUB_VERBYTES = bytes.fromhex("0488b21e") XPRV_VERBYTES = bytes.fromhex("0488ade4") - P2PKH_VERBYTE = 0x00 - P2SH_VERBYTE = 0x05 - WIF_BYTE = 0x80 + P2PKH_VERBYTE = bytes.fromhex("00") + P2SH_VERBYTE = bytes.fromhex("05"), + WIF_BYTE = bytes.fromhex("80") GENESIS_HASH = ('000000000019d6689c085ae165831e93' '4ff763ae46a2a6c172b3f1b60a8ce26f') TX_COUNT = 156335304 @@ -328,9 +327,9 @@ class BitcoinTestnet(Bitcoin): IRC_PREFIX = None XPUB_VERBYTES = bytes.fromhex("043587cf") XPRV_VERBYTES = bytes.fromhex("04358394") - P2PKH_VERBYTE = 0x6f - P2SH_VERBYTE = 0xc4 - WIF_BYTE = 0xef + P2PKH_VERBYTE = bytes.fromhex("6f") + P2SH_VERBYTE = bytes.fromhex("c4"), + WIF_BYTE = bytes.fromhex("ef") GENESIS_HASH = ('000000000933ea01ad0ee984209779ba' 'aec3ced90fa3f408719526f8d77f4943') REORG_LIMIT = 2000 @@ -370,9 +369,9 @@ class Litecoin(Coin): NET = "mainnet" XPUB_VERBYTES = bytes.fromhex("019da462") XPRV_VERBYTES = bytes.fromhex("019d9cfe") - P2PKH_VERBYTE = 0x30 - P2SH_VERBYTE = 0x05 - WIF_BYTE = 0xb0 + P2PKH_VERBYTE = bytes.fromhex("30") + P2SH_VERBYTE = bytes.fromhex("05"), + WIF_BYTE = bytes.fromhex("b0") GENESIS_HASH = ('12a765e31ffd4059bada1e25190f6e98' 'c99d9714d334efa41a195a7e7e04bfe2') TX_COUNT = 8908766 @@ -381,6 +380,7 @@ class Litecoin(Coin): IRC_PREFIX = "EL_" IRC_CHANNEL = "#electrum-ltc" RPC_PORT = 9332 + REORG_LIMIT = 800 class LitecoinTestnet(Litecoin): @@ -388,9 +388,9 @@ class LitecoinTestnet(Litecoin): NET = "testnet" XPUB_VERBYTES = bytes.fromhex("0436f6e1") XPRV_VERBYTES = bytes.fromhex("0436ef7d") - P2PKH_VERBYTE = 0x6f - P2SH_VERBYTE = 0xc4 - WIF_BYTE = 0xef + P2PKH_VERBYTE = bytes.fromhex("6f") + P2SH_VERBYTE = bytes.fromhex("c4"), + WIF_BYTE = bytes.fromhex("ef") GENESIS_HASH = ('f5ae71e26c74beacc88382716aced69c' 'ddf3dffff24f384e1808905e0188f68f') @@ -402,11 +402,16 @@ class Namecoin(Coin): NET = "mainnet" XPUB_VERBYTES = bytes.fromhex("d7dd6370") XPRV_VERBYTES = bytes.fromhex("d7dc6e31") - P2PKH_VERBYTE = 0x34 - P2SH_VERBYTE = 0x0d - WIF_BYTE = 0xe4 + P2PKH_VERBYTE = bytes.fromhex("34") + P2SH_VERBYTE = bytes.fromhex("0d"), + WIF_BYTE = bytes.fromhex("e4") GENESIS_HASH = ('000000000062b72c5e2ceb45fbc8587e' '807c155b0da735e6483dfba2f0a9c770') + TX_COUNT = 4415768 + TX_COUNT_HEIGHT = 329065 + TX_PER_BLOCK = 10 + IRC_PREFIX = "E_" + IRC_CHANNEL = "#electrum-nmc" class NamecoinTestnet(Namecoin): @@ -415,10 +420,11 @@ class NamecoinTestnet(Namecoin): NET = "testnet" XPUB_VERBYTES = bytes.fromhex("043587cf") XPRV_VERBYTES = bytes.fromhex("04358394") - P2PKH_VERBYTE = 0x6f - P2SH_VERBYTE = 0xc4 - WIF_BYTE = 0xef - # TODO add GENESIS_HASH + P2PKH_VERBYTE = bytes.fromhex("6f") + P2SH_VERBYTE = bytes.fromhex("c4"), + WIF_BYTE = bytes.fromhex("ef") + GENESIS_HASH = ('00000007199508e34a9ff81e6ec0c477' + 'a4cccff2a4767a8eee39c11db367b008') # For DOGE there is disagreement across sites like bip32.org and @@ -429,11 +435,17 @@ class Dogecoin(Coin): NET = "mainnet" XPUB_VERBYTES = bytes.fromhex("02facafd") XPRV_VERBYTES = bytes.fromhex("02fac398") - P2PKH_VERBYTE = 0x1e - P2SH_VERBYTE = 0x16 - WIF_BYTE = 0x9e + P2PKH_VERBYTE = bytes.fromhex("1e") + P2SH_VERBYTE = bytes.fromhex("16"), + WIF_BYTE = bytes.fromhex("9e") GENESIS_HASH = ('1a91e3dace36e2be3bf030a65679fe82' '1aa1d6ef92e7c9902eb318182c355691') + TX_COUNT = 27583427 + TX_COUNT_HEIGHT = 1604979 + TX_PER_BLOCK = 20 + IRC_PREFIX = "E_" + IRC_CHANNEL = "#electrum-doge" + REORG_LIMIT = 2000 class DogecoinTestnet(Dogecoin): @@ -442,9 +454,9 @@ class DogecoinTestnet(Dogecoin): NET = "testnet" XPUB_VERBYTES = bytes.fromhex("0432a9a8") XPRV_VERBYTES = bytes.fromhex("0432a243") - P2PKH_VERBYTE = 0x71 - P2SH_VERBYTE = 0xc4 - WIF_BYTE = 0xf1 + P2PKH_VERBYTE = bytes.fromhex("71") + P2SH_VERBYTE = bytes.fromhex("c4"), + WIF_BYTE = bytes.fromhex("f1") GENESIS_HASH = ('bb0a78264637406b6360aad926284d54' '4d7049f45189db5664f3c4d07350559e') @@ -458,9 +470,9 @@ class Dash(Coin): XPRV_VERBYTES = bytes.fromhex("02fe52f8") GENESIS_HASH = ('00000ffd590b1485b3caadc19b22e637' '9c733355108f107a430458cdf3407ab6') - P2PKH_VERBYTE = 0x4c - P2SH_VERBYTE = 0x10 - WIF_BYTE = 0xcc + P2PKH_VERBYTE = bytes.fromhex("4c") + P2SH_VERBYTE = bytes.fromhex("10"), + WIF_BYTE = bytes.fromhex("cc") TX_COUNT_HEIGHT = 569399 TX_COUNT = 2157510 TX_PER_BLOCK = 4 @@ -490,9 +502,9 @@ class DashTestnet(Dash): XPRV_VERBYTES = bytes.fromhex("3a8061a0") GENESIS_HASH = ('00000bafbc94add76cb75e2ec9289483' '7288a481e5c005f6563d91623bf8bc2c') - P2PKH_VERBYTE = 0x8c - P2SH_VERBYTE = 0x13 - WIF_BYTE = 0xef + P2PKH_VERBYTE = bytes.fromhex("8c") + P2SH_VERBYTE = bytes.fromhex("13"), + WIF_BYTE = bytes.fromhex("ef") TX_COUNT_HEIGHT = 101619 TX_COUNT = 132681 TX_PER_BLOCK = 1 @@ -510,9 +522,9 @@ class Argentum(Coin): NET = "mainnet" XPUB_VERBYTES = bytes.fromhex("0488b21e") XPRV_VERBYTES = bytes.fromhex("0488ade4") - P2PKH_VERBYTE = 0x17 - P2SH_VERBYTE = 0x05 - WIF_BYTE = 0x97 + P2PKH_VERBYTE = bytes.fromhex("17") + P2SH_VERBYTE = bytes.fromhex("05"), + WIF_BYTE = bytes.fromhex("97") GENESIS_HASH = ('88c667bc63167685e4e4da058fffdfe8' 'e007e5abffd6855de52ad59df7bb0bb2') TX_COUNT = 2263089 @@ -528,9 +540,9 @@ class ArgentumTestnet(Argentum): NET = "testnet" XPUB_VERBYTES = bytes.fromhex("043587cf") XPRV_VERBYTES = bytes.fromhex("04358394") - P2PKH_VERBYTE = 0x6f - P2SH_VERBYTE = 0xc4 - WIF_BYTE = 0xef + P2PKH_VERBYTE = bytes.fromhex("6f") + P2SH_VERBYTE = bytes.fromhex("c4"), + WIF_BYTE = bytes.fromhex("ef") REORG_LIMIT = 2000 @@ -540,9 +552,9 @@ class DigiByte(Coin): NET = "mainnet" XPUB_VERBYTES = bytes.fromhex("0488b21e") XPRV_VERBYTES = bytes.fromhex("0488ade4") - P2PKH_VERBYTE = 0x1E - P2SH_VERBYTE = 0x05 - WIF_BYTE = 0x80 + P2PKH_VERBYTE = bytes.fromhex("1E") + P2SH_VERBYTE = bytes.fromhex("05"), + WIF_BYTE = bytes.fromhex("80") GENESIS_HASH = ('7497ea1b465eb39f1c8f507bc877078f' 'e016d6fcb6dfad3a64c98dcc6e1e8496') TX_COUNT = 1046018 @@ -557,9 +569,9 @@ class DigiByteTestnet(DigiByte): NET = "testnet" XPUB_VERBYTES = bytes.fromhex("043587cf") XPRV_VERBYTES = bytes.fromhex("04358394") - P2PKH_VERBYTE = 0x6f - P2SH_VERBYTE = 0xc4 - WIF_BYTE = 0xef + P2PKH_VERBYTE = bytes.fromhex("6f") + P2SH_VERBYTE = bytes.fromhex("c4"), + WIF_BYTE = bytes.fromhex("ef") GENESIS_HASH = ('b5dca8039e300198e5fe7cd23bdd1728' 'e2a444af34c447dbd0916fa3430a68c2') IRC_PREFIX = "DET_" @@ -574,9 +586,9 @@ class FairCoin(Coin): NET = "mainnet" XPUB_VERBYTES = bytes.fromhex("0488b21e") XPRV_VERBYTES = bytes.fromhex("0488ade4") - P2PKH_VERBYTE = 0x5f - P2SH_VERBYTE = 0x24 - WIF_BYTE = 0xdf + P2PKH_VERBYTE = bytes.fromhex("5f") + P2SH_VERBYTE = bytes.fromhex("24"), + WIF_BYTE = bytes.fromhex("df") GENESIS_HASH=('1f701f2b8de1339dc0ec908f3fb6e9b0' 'b870b6f20ba893e120427e42bbc048d7') TX_COUNT = 1000