Browse Source

Better handle base58 version bytes and allow for a >1 byte version

master
John L. Jegutanis 8 years ago
committed by Neil Booth
parent
commit
6b1b9d01f2
  1. 132
      lib/coins.py

132
lib/coins.py

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

Loading…
Cancel
Save