|
|
@ -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 |
|
|
|