Files
plm-electrumx/src/electrumx/lib/coins.py
T

3866 lines
114 KiB
Python
Raw Normal View History

# Copyright (c) 2016-2017, Neil Booth
# Copyright (c) 2017, the ElectrumX authors
#
# All rights reserved.
#
# The MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
'''Module providing coin abstraction.
Anything coin-specific should go in this file and be subclassed where
necessary for appropriate handling.
'''
import re
import struct
from dataclasses import dataclass
from decimal import Decimal
from functools import partial
from hashlib import sha256
from typing import Sequence, Tuple, Optional, Type
import electrumx.lib.util as util
from electrumx.lib.hash import Base58, double_sha256, hash_to_hex_str
from electrumx.lib.hash import HASHX_LEN, hex_str_to_hash
from electrumx.lib.script import (_match_ops, Script, ScriptError,
ScriptPubKey, OpCodes)
import electrumx.lib.tx as lib_tx
from electrumx.lib.tx import Tx
import electrumx.lib.tx_dash as lib_tx_dash
import electrumx.lib.tx_axe as lib_tx_axe
import electrumx.server.block_processor as block_proc
import electrumx.server.daemon as daemon
from electrumx.server.session import (ElectrumX, DashElectrumX,
SmartCashElectrumX, AuxPoWElectrumX,
NameIndexElectrumX, NameIndexAuxPoWElectrumX)
@dataclass(slots=True)
class Block:
raw: bytes
header: bytes
transactions: Sequence[Tx]
class CoinError(Exception):
'''Exception raised for coin-related errors.'''
class Coin:
'''Base class of coin hierarchy.'''
REORG_LIMIT = 200
# Not sure if these are coin-specific
RPC_URL_REGEX = re.compile('.+@(\\[[0-9a-fA-F:]+\\]|[^:]+)(:[0-9]+)?')
VALUE_PER_COIN = 100000000
CHUNK_SIZE = 2016
BASIC_HEADER_SIZE = 80
STATIC_BLOCK_HEADERS = True
SESSIONCLS = ElectrumX
DESERIALIZER = lib_tx.Deserializer
DAEMON = daemon.Daemon
BLOCK_PROCESSOR = block_proc.BlockProcessor
P2PKH_VERBYTE = bytes.fromhex("00")
P2SH_VERBYTES = (bytes.fromhex("05"),)
ENCODE_CHECK = Base58.encode_check
DECODE_CHECK = Base58.decode_check
GENESIS_HASH = ('000000000019d6689c085ae165831e93'
'4ff763ae46a2a6c172b3f1b60a8ce26f') # 'hum' byte-order
GENESIS_ACTIVATION = 100_000_000
# max byte-size of single jsonrpc message
# note: we should probably be able to serve a client asking for the largest consensus-valid tx.
# For Bitcoin, that is 4 M weight units, i.e. 4 MB on the p2p wire.
# Double that due to our JSON-RPC hex-encoding, plus overhead, we need to send 8+ MB.
# When receiving from a client, e.g. to broadcast, such a tx would be non-standard anyway.
DEFAULT_MAX_SEND = 8_100_000
DEFAULT_MAX_RECV = 1_000_000
MEMPOOL_HISTOGRAM_REFRESH_SECS = 500
# first bin size in vbytes. smaller bins mean more precision but also bandwidth:
MEMPOOL_COMPACT_HISTOGRAM_BINSIZE = 30_000
# Peer discovery
PEER_DEFAULT_PORTS = {'t': '50001', 's': '50002'}
PEERS = []
CRASH_CLIENT_VER = None
BLACKLIST_URL = None
ESTIMATEFEE_MODES = (None, 'CONSERVATIVE', 'ECONOMICAL')
RPC_PORT: int
NAME: str
NET: str | None
MIN_REQUIRED_DAEMON_VERSION: Optional[str] = None
REQUIRED_DAEMON_INDEXES: Sequence[str] = tuple()
# only used for initial db sync ETAs:
TX_COUNT_HEIGHT: int # at a given snapshot of the chain,
TX_COUNT: int # there have been this many txs so far,
TX_PER_BLOCK: int # and from that height onwards, we guess this many txs per block
@classmethod
def lookup_coin_class(cls, name: str, net: str) -> Type['Coin']:
'''Return a coin class given name and network.
Raise an exception if unrecognised.'''
req_attrs = ('TX_COUNT', 'TX_COUNT_HEIGHT', 'TX_PER_BLOCK')
for coin in util.subclasses(Coin):
if (
coin.NAME.lower() == name.lower()
and coin.NET is not None
and coin.NET.lower() == net.lower()
):
missing = [
attr
for attr in req_attrs
if not hasattr(coin, attr)
]
if missing:
raise CoinError(
f'coin {name} missing {missing} attributes'
)
return coin
raise CoinError(f'unknown coin {name} and network {net} combination')
@classmethod
def sanitize_url(cls, url: str):
# Remove surrounding ws and trailing /s
url = url.strip().rstrip('/')
match = cls.RPC_URL_REGEX.match(url)
if not match:
raise CoinError(f'invalid daemon URL: "{url}"')
if match.groups()[1] is None:
url = f'{url}:{cls.RPC_PORT:d}'
if not url.startswith(('http://', 'https://')):
url = f'http://{url}'
return url + '/'
@classmethod
def max_fetch_blocks(cls, height: int) -> int:
if height < 130000:
return 1000
return 100
@classmethod
def genesis_block(cls, block: bytes) -> bytes:
'''Check the Genesis block is the right one for this coin.
Return the block less its unspendable coinbase.
'''
header = cls.block_header(block, 0)
header_hex_hash = hash_to_hex_str(cls.header_hash_rev(header))
if header_hex_hash != cls.GENESIS_HASH:
raise CoinError(f'genesis block has hash {header_hex_hash} '
f'expected {cls.GENESIS_HASH}')
return header + b'\0'
@classmethod
def hashX_from_script(cls, script):
'''Returns a hashX from a script.'''
return sha256(script).digest()[:HASHX_LEN]
@classmethod
def address_to_hashX(cls, address):
'''Return a hashX given a coin address.'''
return cls.hashX_from_script(cls.pay_to_address_script(address))
@classmethod
def hash160_to_P2PKH_script(cls, hash160):
return ScriptPubKey.P2PKH_script(hash160)
@classmethod
def hash160_to_P2PKH_hashX(cls, hash160):
return cls.hashX_from_script(cls.hash160_to_P2PKH_script(hash160))
@classmethod
def pay_to_address_script(cls, address):
'''Return a pubkey script that pays to a pubkey hash.
Pass the address (either P2PKH or P2SH) in base58 form.
note(ghost43): looks mainly needed for serving the altcoin Dash(Coin)'s "masternode.list" RPC.
Barring that, we could rip out the whole base58 encoder/decoder.
'''
raw = cls.DECODE_CHECK(address)
# Require version byte(s) plus hash160.
verbyte = -1
verlen = len(raw) - 20
if verlen > 0:
verbyte, hash160 = raw[:verlen], raw[verlen:]
if verbyte == cls.P2PKH_VERBYTE:
return cls.hash160_to_P2PKH_script(hash160)
if verbyte in cls.P2SH_VERBYTES:
return ScriptPubKey.P2SH_script(hash160)
raise CoinError(f'invalid address: {address}')
@classmethod
def header_hash_rev(cls, header: bytes) -> bytes:
'''Given a header return hash. (reverse of human-readable blockhash)'''
return double_sha256(header)
@classmethod
def header_prevhash_rev(cls, header: bytes) -> bytes:
'''Given a header return previous hash. (reverse of human-readable blockhash)'''
return header[4:36]
@classmethod
def static_header_offset(cls, height: int) -> int:
'''Given a header height return its offset in the headers file.
If header sizes change at some point, this is the only code
that needs updating.'''
assert cls.STATIC_BLOCK_HEADERS
return height * cls.BASIC_HEADER_SIZE
@classmethod
def static_header_len(cls, height: int) -> int:
'''Given a header height return its length.'''
return (cls.static_header_offset(height + 1)
- cls.static_header_offset(height))
@classmethod
def block_header(cls, block: bytes, height: int) -> bytes:
'''Returns the block header given a block and its height.'''
return block[:cls.static_header_len(height)]
@classmethod
def block(cls, raw_block: bytes, height: int) -> 'Block':
'''Return a Block namedtuple given a raw block and its height.'''
header = cls.block_header(raw_block, height)
txs = cls.DESERIALIZER(raw_block, start=len(header)).read_tx_block()
return Block(raw_block, header, txs)
@classmethod
def decimal_value(cls, value: int) -> Decimal:
'''Return the number of standard coin units as a Decimal given a
quantity of smallest units.
For example 1 BTC is returned for 100 million satoshis.
'''
return Decimal(value) / cls.VALUE_PER_COIN
@classmethod
def warn_old_client_on_tx_broadcast(cls, _client_ver):
return False
@classmethod
def bucket_estimatefee_block_target(cls, n: int) -> int:
'''For caching purposes, it might be desirable to restrict the
set of values that can be queried as an estimatefee block target.
'''
return n
class Bitcoin(Coin):
"""Base class for Actual non-altcoin Bitcoin, including its various test networks."""
NAME = "Bitcoin"
NET = None # we are an abstract base class
MEMPOOL_HISTOGRAM_REFRESH_SECS = 120
DESERIALIZER = lib_tx.DeserializerSegWit
CRASH_CLIENT_VER = (3, 2, 3)
# core version 28 introduced 1p1c package relay required for protocol 1.6
# core version 31 introduced "txospenderindex", required for protocol 1.7
MIN_REQUIRED_DAEMON_VERSION = "31.0"
REQUIRED_DAEMON_INDEXES = ("txindex", "txospenderindex",)
@classmethod
def warn_old_client_on_tx_broadcast(cls, client_ver):
if client_ver < (3, 3, 3):
return ('<br/><br/>'
'Your transaction was successfully broadcast.<br/><br/>'
'However, you are using a VULNERABLE version of Electrum.<br/>'
'Download the new version from the usual place:<br/>'
'https://electrum.org/'
'<br/><br/>')
return False
@classmethod
def bucket_estimatefee_block_target(cls, n: int) -> int:
# values based on https://github.com/bitcoin/bitcoin/blob/af05bd9e1e362c3148e3b434b7fac96a9a5155a1/src/policy/fees.h#L131 # noqa
if n <= 1:
return 1
if n <= 12:
return n
if n == 25: # so common that we make an exception for it
return n
if n <= 48:
return n // 2 * 2
if n <= 1008:
return n // 24 * 24
return 1008
class BitcoinMainnet(Bitcoin):
SHORTNAME = "BTC"
NET = "mainnet"
RPC_PORT = 8332
TX_COUNT = 1_368_093_517
TX_COUNT_HEIGHT = 951_801
TX_PER_BLOCK = 3000
BLACKLIST_URL = 'https://electrum.org/blacklist.json'
PEERS = [
'electrum.vom-stausee.de s t',
'electrum.hsmiths.com s t',
'helicarrier.bauerj.eu s t',
'electrum.hodlister.co s',
'electrum3.hodlister.co s',
'btc.usebsv.com s50006',
'fortress.qtornado.com s443 t',
'ecdsa.net s110 t',
'e2.keff.org s t',
'currentlane.lovebitco.in s t',
'electrum.jochen-hoenicke.de s50005 t50003',
'vps5.hsmiths.com s',
'electrum.emzy.de s',
'electrum1.cipig.net t10000 s20000',
'ulrichard.ch s',
'hodlers.beer s',
'5.9.83.108 s',
'v7gtzf7nua6hdmb2wtqaqioqmesdb4xrlly4zwr7bvayxv2bpg665pqd.onion t',
'qeqgdlw2ezf3uabook2ny3lztjxxzeyyoqw2k7cempzvqpknbmevhmyd.onion t',
'kciybn4d4vuqvobdl2kdp3r2rudqbqvsymqwg4jomzft6m6gaibaf6yd.onion t',
'explorerzydxu5ecjrkwceayqybizmpjjznk5izmitf2modhcusuqlid.onion t110',
'v7o2hkemnt677k3jxcbosmjjxw3p5khjyu7jwv7orfy6rwtkizbshwqd.onion t57001',
'nf365b5sbzk5j4jreimskffwnfpka7qtamyni5doohoom3g63o5tldad.onion t',
]
class BitcoinTestnetMixin: # also subclassed by altcoins.
SHORTNAME = "XTN"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("6f")
P2SH_VERBYTES = (bytes.fromhex("c4"),)
GENESIS_HASH = ('000000000933ea01ad0ee984209779ba'
'aec3ced90fa3f408719526f8d77f4943')
REORG_LIMIT = 8000
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 21
RPC_PORT = 18332
PEER_DEFAULT_PORTS = {'t': '51001', 's': '51002'}
class BitcoinTestnet3(BitcoinTestnetMixin, Bitcoin):
'''Bitcoin Testnet3 for Bitcoin Core >= 0.13.1.'''
NET = "testnet"
TX_COUNT = 536_377_099
TX_COUNT_HEIGHT = 4_966_614
TX_PER_BLOCK = 100
PEERS = [
'testnet.qtornado.com s t',
'blackie.c3-soft.com s57006 t57005',
'electrum.blockstream.info t60001 s60002',
'testnet.aranguren.org s t',
'v22019051929289916.bestsrv.de s50002 t50001',
'explorerzydxu5ecjrkwceayqybizmpjjznk5izmitf2modhcusuqlid.onion t143',
'gsw6sn27quwf6u3swgra6o7lrp5qau6kt3ymuyoxgkth6wntzm2bjwyd.onion s51002 t51001',
'3tc6nefii2fwoc66dqvrwcyj64dd3r35ihgxvp4u37itsopns5fjtead.onion s50002 t50001',
]
class BitcoinRegtest(BitcoinTestnetMixin, Bitcoin):
NET = "regtest"
GENESIS_HASH = ('0f9188f13cb7b2c71f2a335e3a4fc328'
'bf5beb436012afca590b1a11466e2206')
PEERS = []
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
RPC_PORT = 18443
class BitcoinSignet(BitcoinTestnetMixin, Bitcoin):
NET = "signet"
GENESIS_HASH = ('00000008819873e925422c1ff0f99f7c'
'c9bbb232af63a077a480a3633bee1ef6')
PEERS = []
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
RPC_PORT = 38332
class BitcoinMutinynet(BitcoinTestnetMixin, Bitcoin):
# custom signet https://github.com/MutinyWallet/mutiny-net/
# see https://github.com/f321x/simple-mutinynet for docker setup
NET = "mutinynet"
GENESIS_HASH = ('00000008819873e925422c1ff0f99f7c' # same as Signet
'c9bbb232af63a077a480a3633bee1ef6')
PEERS = [
'electrum.mutinynet.com t50001', # doesn't seem to serve server.features
'5.9.83.108 s51234',
]
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
RPC_PORT = 38332
class BitcoinTestnet4(BitcoinTestnetMixin, Bitcoin):
NET = "testnet4"
GENESIS_HASH = ('00000000da84f2bafbbc53dee25a72ae'
'507ff4914b867c565be350b0da8bf043')
PEERS = [
'blackie.c3-soft.com s57010 t57009',
'testnet4-electrumx.wakiyamap.dev',
'13.212.194.61 s60002 t50001',
'v22019051929289916.bestsrv.de s60002 t60001',
'fulcrum.theuplink.net s60002',
'134.199.227.217 s50002 t50001',
'bitcoin.stagemole.eu s5010 t5000',
'testnet4.qtornado.com s51012 t51011',
'gsw6sn27quwf6u3swgra6o7lrp5qau6kt3ymuyoxgkth6wntzm2bjwyd.onion s52002 t52001',
]
TX_COUNT = 14_410_912
TX_COUNT_HEIGHT = 137_121
TX_PER_BLOCK = 100
RPC_PORT = 48332
######################################################################
# Non-Bitcoin stuff goes strictly below this line.
######################################################################
class AuxPowMixin:
STATIC_BLOCK_HEADERS = False
DESERIALIZER = lib_tx.DeserializerAuxPow
SESSIONCLS = AuxPoWElectrumX
TRUNCATED_HEADER_SIZE = 80
# AuxPoW headers are significantly larger, so the DEFAULT_MAX_SEND from
# Bitcoin is insufficient. In Namecoin mainnet, 5 MB wasn't enough to
# sync, while 10 MB worked fine.
DEFAULT_MAX_SEND = 10000000
@classmethod
def header_hash_rev(cls, header):
'''Given a header return hash'''
return double_sha256(header[:cls.BASIC_HEADER_SIZE])
@classmethod
def block_header(cls, block, height):
'''Return the AuxPow block header bytes'''
deserializer = cls.DESERIALIZER(block)
return deserializer.read_header(cls.BASIC_HEADER_SIZE)
class EquihashMixin:
STATIC_BLOCK_HEADERS = False
BASIC_HEADER_SIZE = 140 # Excluding Equihash solution
DESERIALIZER = lib_tx.DeserializerEquihash
@classmethod
def block_header(cls, block, height):
'''Return the block header bytes'''
deserializer = cls.DESERIALIZER(block)
return deserializer.read_header(cls.BASIC_HEADER_SIZE)
class ScryptMixin:
DESERIALIZER = lib_tx.DeserializerTxTime
HEADER_HASH = None
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
if cls.HEADER_HASH is None:
# Requires OpenSSL 1.1.0+
from hashlib import scrypt
cls.HEADER_HASH = lambda x: scrypt(x, salt=x, n=1024, r=1, p=1, dklen=32)
version, = util.unpack_le_uint32_from(header)
if version > 6:
return super().header_hash_rev(header)
else:
return cls.HEADER_HASH(header)
class KomodoMixin:
P2PKH_VERBYTE = bytes.fromhex("3C")
P2SH_VERBYTES = (bytes.fromhex("55"),)
GENESIS_HASH = ('027e3758c3a65b12aa1046462b486d0a'
'63bfa1beae327897f56c5cfb7daaae71')
DESERIALIZER = lib_tx.DeserializerZcash
class NameMixin:
DATA_PUSH_MULTIPLE = -2
@classmethod
def interpret_name_prefix(cls, script, possible_ops):
"""Interprets a potential name prefix
Checks if the given script has a name prefix. If it has, the
name prefix is split off the actual address script, and its parsed
fields (e.g. the name) returned.
possible_ops must be an array of arrays, defining the structures
of name prefixes to look out for. Each array can consist of
actual opcodes, -1 for ignored data placeholders, -2 for
multiple ignored data placeholders and strings for named placeholders.
Whenever a data push matches a named placeholder,
the corresponding value is put into a dictionary the placeholder name
as key, and the dictionary of matches is returned."""
try:
ops = Script.get_ops(script)
except ScriptError:
return None, script
name_op_count = None
for pops in possible_ops:
# Start by translating named placeholders to -1 values, and
# keeping track of which op they corresponded to.
template = []
named_index = {}
n = len(pops)
offset = 0
for i, op in enumerate(pops):
if op == cls.DATA_PUSH_MULTIPLE:
# Emercoin stores value in multiple placeholders
# Script structure: https://git.io/fjuRu
added, template = cls._add_data_placeholders_to_template(ops[i:], template)
offset += added - 1 # subtract the "DATA_PUSH_MULTIPLE" opcode
elif isinstance(op, str):
template.append(-1)
named_index[op] = i + offset
else:
template.append(op)
n += offset
if not _match_ops(ops[:n], template):
continue
name_op_count = n
named_values = {key: ops[named_index[key]] for key in named_index}
break
if name_op_count is None:
return None, script
name_end_pos = cls.find_end_position_of_name(script, name_op_count)
address_script = script[name_end_pos:]
return named_values, address_script
@classmethod
def _add_data_placeholders_to_template(cls, opcodes, template):
num_dp = cls._read_data_placeholders_count(opcodes)
num_2drop = num_dp // 2
num_drop = num_dp % 2
two_drops = [OpCodes.OP_2DROP] * num_2drop
one_drops = [OpCodes.OP_DROP] * num_drop
elements_added = num_dp + num_2drop + num_drop
placeholders = [-1] * num_dp
drops = two_drops + one_drops
return elements_added, template + placeholders + drops
@classmethod
def _read_data_placeholders_count(cls, opcodes):
data_placeholders = 0
for opcode in opcodes:
if isinstance(opcode, tuple):
data_placeholders += 1
else:
break
return data_placeholders
@staticmethod
def find_end_position_of_name(script, length):
"""Finds the end position of the name data
Given the number of opcodes in the name prefix (length), returns the
index into the byte array of where the name prefix ends."""
n = 0
for _i in range(length):
# Content of this loop is copied from Script.get_ops's loop
op = script[n]
n += 1
if op <= OpCodes.OP_PUSHDATA4:
# Raw bytes follow
if op < OpCodes.OP_PUSHDATA1:
dlen = op
elif op == OpCodes.OP_PUSHDATA1:
dlen = script[n]
n += 1
elif op == OpCodes.OP_PUSHDATA2:
dlen, = struct.unpack('<H', script[n: n + 2])
n += 2
else:
dlen, = struct.unpack('<I', script[n: n + 4])
n += 4
if n + dlen > len(script):
raise IndexError
n += dlen
return n
class NameIndexMixin(NameMixin):
"""Shared definitions for coins that have a name index
This class defines common functions and logic for coins that have
a name index in addition to the index by address / script."""
BLOCK_PROCESSOR = block_proc.NameIndexBlockProcessor
SESSIONCLS = NameIndexElectrumX
NAME_EXPIRATION = None
@classmethod
def build_name_index_script(cls, name):
"""Returns the script by which names are indexed"""
from electrumx.lib.script import Script
res = bytearray()
res.append(cls.OP_NAME_UPDATE)
res += Script.push_data(name)
res += Script.push_data(b'')
res.append(OpCodes.OP_2DROP)
res.append(OpCodes.OP_DROP)
res.append(OpCodes.OP_RETURN)
return bytes(res)
@classmethod
def split_name_script(cls, script):
named_values, address_script = cls.interpret_name_prefix(script, cls.NAME_OPERATIONS)
if named_values is None or "name" not in named_values:
return None, address_script
name_index_script = cls.build_name_index_script(named_values["name"][1])
return name_index_script, address_script
@classmethod
def hashX_from_script(cls, script):
_, address_script = cls.split_name_script(script)
return super().hashX_from_script(address_script)
@classmethod
def address_from_script(cls, script):
_, address_script = cls.split_name_script(script)
return super().address_from_script(address_script)
@classmethod
def name_hashX_from_script(cls, script):
name_index_script, _ = cls.split_name_script(script)
if name_index_script is None:
return None
return super().hashX_from_script(name_index_script)
class NameIndexAuxPoWMixin(NameIndexMixin, AuxPowMixin):
SESSIONCLS = NameIndexAuxPoWElectrumX
class PrimeChainPowMixin:
STATIC_BLOCK_HEADERS = False
DESERIALIZER = lib_tx.DeserializerPrimecoin
@classmethod
def block_header(cls, block, height):
'''Return the block header bytes'''
deserializer = cls.DESERIALIZER(block)
return deserializer.read_header(cls.BASIC_HEADER_SIZE)
class Verge(Coin):
NAME = "Verge"
SHORTNAME = "XVG"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("30")
P2SH_VERBYTES = [bytes.fromhex("33")]
GENESIS_HASH = ('00000fc63692467faeb20cdb3b53200d'
'c601d75bdfa1001463304cc790d77278')
RPC_PORT = 20102
PEERS = [
'electrumx-verge.cloud s50002 t50001',
'electrum-verge.cloud s50002 t50001',
]
TX_COUNT = 500000
TX_COUNT_HEIGHT = 3082138
TX_PER_BLOCK = 1
DESERIALIZER = lib_tx.DeserializerVerge
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
import scrypt
return scrypt.hash(header, header, 1024, 1, 1, 32)
class HOdlcoin(Coin):
NAME = "HOdlcoin"
SHORTNAME = "HODLC"
NET = "mainnet"
BASIC_HEADER_SIZE = 88
P2PKH_VERBYTE = bytes.fromhex("28")
GENESIS_HASH = ('008872e5582924544e5c707ee4b839bb'
'82c28a9e94e917c94b40538d5658c04b')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 258858
TX_COUNT_HEIGHT = 382138
TX_PER_BLOCK = 5
class BitcoinSV(Coin):
NAME = "BitcoinSV"
SHORTNAME = "BSV"
NET = "mainnet"
RPC_PORT = 8332
TX_COUNT = 267318795
TX_COUNT_HEIGHT = 557037
TX_PER_BLOCK = 400
PEERS = [
'electrumx.bitcoinsv.io s',
'satoshi.vision.cash s',
'sv.usebsv.com s t',
'sv.jochen-hoenicke.de s t',
'sv.satoshi.io s t',
]
GENESIS_ACTIVATION = 620_538
class BitcoinCash(Coin):
NAME = "BitcoinCash"
SHORTNAME = "BCH"
NET = "mainnet"
RPC_PORT = 8332
TX_COUNT = 265479628
TX_COUNT_HEIGHT = 556592
TX_PER_BLOCK = 400
PEERS = [
'bch.imaginary.cash s t',
'electroncash.dk s t',
'electrum.imaginary.cash s t',
'bch.loping.net s t',
'electroncash.de s t',
'blackie.c3-soft.com s t',
]
BLOCK_PROCESSOR = block_proc.LTORBlockProcessor
@classmethod
def warn_old_client_on_tx_broadcast(cls, client_ver):
if client_ver < (3, 3, 4):
return ('<br/><br/>'
'Your transaction was successfully broadcast.<br/><br/>'
'However, you are using a VULNERABLE version of Electron Cash.<br/>'
'Download the latest version from this web site ONLY:<br/>'
'https://electroncash.org/'
'<br/><br/>')
return False
class BitcoinGold(EquihashMixin, Coin):
CHUNK_SIZE = 252
NAME = "BitcoinGold"
SHORTNAME = "BTG"
NET = "mainnet"
FORK_HEIGHT = 491407
P2PKH_VERBYTE = bytes.fromhex("26")
P2SH_VERBYTES = (bytes.fromhex("17"),)
DESERIALIZER = lib_tx.DeserializerEquihashSegWit
TX_COUNT = 265026255
TX_COUNT_HEIGHT = 499923
TX_PER_BLOCK = 50
REORG_LIMIT = 1000
RPC_PORT = 8332
PEERS = [
'electrumx-eu.bitcoingold.org s50002 t50001',
'electrumx-us.bitcoingold.org s50002 t50001',
]
@classmethod
def header_hash_rev(cls, header):
'''Given a header return hash'''
height, = util.unpack_le_uint32_from(header, 68)
if height >= cls.FORK_HEIGHT:
return double_sha256(header)
else:
return double_sha256(header[:68] + header[100:112])
class BitcoinGoldTestnet(BitcoinGold):
FORK_HEIGHT = 1
SHORTNAME = "TBTG"
P2PKH_VERBYTE = bytes.fromhex("6F")
P2SH_VERBYTES = (bytes.fromhex("C4"),)
TX_COUNT = 0
TX_COUNT_HEIGHT = 1
NET = 'testnet'
RPC_PORT = 18332
GENESIS_HASH = ('00000000e0781ebe24b91eedc293adfe'
'a2f557b53ec379e78959de3853e6f9f6')
PEERS = [
'test-node1.bitcoingold.org s50002',
'test-node2.bitcoingold.org s50002',
'test-node3.bitcoingold.org s50002',
]
class BitcoinGoldRegtest(BitcoinGold):
FORK_HEIGHT = 2000
SHORTNAME = "TBTG"
P2PKH_VERBYTE = bytes.fromhex("6F")
P2SH_VERBYTES = (bytes.fromhex("C4"),)
TX_COUNT = 0
TX_COUNT_HEIGHT = 1
NET = 'regtest'
RPC_PORT = 18444
GENESIS_HASH = ('0f9188f13cb7b2c71f2a335e3a4fc328'
'bf5beb436012afca590b1a11466e2206')
PEERS = []
class BitcoinDiamond(Coin):
NAME = "BitcoinDiamond"
SHORTNAME = "BCD"
NET = "mainnet"
RPC_PORT = 8332
TX_VERSION = 12
TX_COUNT = 274277819
TX_COUNT_HEIGHT = 498678
TX_PER_BLOCK = 50
REORG_LIMIT = 1000
PEERS = []
VALUE_PER_COIN = 10000000
DESERIALIZER = lib_tx.DeserializerBitcoinDiamondSegWit
class Emercoin(NameMixin, Coin):
NAME = "Emercoin"
SHORTNAME = "EMC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("21")
P2SH_VERBYTES = (bytes.fromhex("5c"),)
GENESIS_HASH = ('00000000bcccd459d036a588d1008fce'
'8da3754b205736f32ddfd35350e84c2d')
TX_COUNT = 217380620
TX_COUNT_HEIGHT = 464000
TX_PER_BLOCK = 1700
VALUE_PER_COIN = 1000000
RPC_PORT = 6662
DESERIALIZER = lib_tx.DeserializerEmercoin
PEERS = []
# Name opcodes
OP_NAME_NEW = OpCodes.OP_1
OP_NAME_UPDATE = OpCodes.OP_2
OP_NAME_DELETE = OpCodes.OP_3
# Valid name prefixes.
NAME_NEW_OPS = (OP_NAME_NEW, OpCodes.OP_DROP, "name", "days",
OpCodes.OP_2DROP, NameMixin.DATA_PUSH_MULTIPLE)
NAME_UPDATE_OPS = (OP_NAME_UPDATE, OpCodes.OP_DROP, "name", "days",
OpCodes.OP_2DROP, NameMixin.DATA_PUSH_MULTIPLE)
NAME_DELETE_OPS = (OP_NAME_DELETE, OpCodes.OP_DROP, "name",
OpCodes.OP_DROP)
NAME_OPERATIONS = (
NAME_NEW_OPS,
NAME_UPDATE_OPS,
NAME_DELETE_OPS,
)
@classmethod
def block_header(cls, block, height):
'''Returns the block header given a block and its height.'''
deserializer = cls.DESERIALIZER(block)
if deserializer.is_merged_block():
return deserializer.read_header(cls.BASIC_HEADER_SIZE)
return block[:cls.static_header_len(height)]
@classmethod
def header_hash_rev(cls, header):
'''Given a header return hash'''
return double_sha256(header[:cls.BASIC_HEADER_SIZE])
@classmethod
def hashX_from_script(cls, script):
_, address_script = cls.interpret_name_prefix(script, cls.NAME_OPERATIONS)
return super().hashX_from_script(address_script)
class BitcoinSVTestnet(BitcoinTestnetMixin, Coin):
'''Bitcoin Testnet for Bitcoin SV daemons.'''
NAME = "BitcoinSV"
PEERS = [
'electrontest.cascharia.com t51001 s51002',
]
GENESIS_ACTIVATION = 1_344_302
class BitcoinSVScalingTestnet(BitcoinSVTestnet):
NET = "scalingtest"
PEERS = [
'stn-server.electrumsv.io t51001 s51002',
]
TX_COUNT = 2015
TX_COUNT_HEIGHT = 5711
TX_PER_BLOCK = 5000
GENESIS_ACTIVATION = 14_896
@classmethod
def max_fetch_blocks(cls, height):
if height <= 10:
return 100
return 3
class BitcoinCashTestnet(BitcoinTestnetMixin, Coin):
'''Bitcoin Testnet for Bitcoin Cash daemons.'''
NAME = "BitcoinCash"
PEERS = [
'bch0.kister.net t s',
'testnet.imaginary.cash t50001 s50002',
'blackie.c3-soft.com t60001 s60002',
]
BLOCK_PROCESSOR = block_proc.LTORBlockProcessor
@classmethod
def warn_old_client_on_tx_broadcast(cls, client_ver):
if client_ver < (3, 3, 4):
return ('<br/><br/>'
'Your transaction was successfully broadcast.<br/><br/>'
'However, you are using a VULNERABLE version of Electron Cash.<br/>'
'Download the latest version from this web site ONLY:<br/>'
'https://electroncash.org/'
'<br/><br/>')
return False
class BitcoinSVRegtest(BitcoinSVTestnet):
NET = "regtest"
GENESIS_HASH = ('0f9188f13cb7b2c71f2a335e3a4fc328'
'bf5beb436012afca590b1a11466e2206')
PEERS = []
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
GENESIS_ACTIVATION = 10_000
class BitcoinNolnet(BitcoinCash):
'''Bitcoin Unlimited nolimit testnet.'''
NET = "nolnet"
GENESIS_HASH = ('0000000057e31bd2066c939a63b7b862'
'3bd0f10d8c001304bdfc1a7902ae6d35')
PEERS = []
REORG_LIMIT = 8000
TX_COUNT = 583589
TX_COUNT_HEIGHT = 8617
TX_PER_BLOCK = 50
RPC_PORT = 28332
PEER_DEFAULT_PORTS = {'t': '52001', 's': '52002'}
# Source: https://github.com/sumcoinlabs/sumcoin
class Sumcoin(Coin):
NAME = "Sumcoin"
SHORTNAME = "SUM"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("3f")
P2SH_VERBYTES = (bytes.fromhex("c8"), bytes.fromhex("05"))
GENESIS_HASH = ('37d4696c5072cd012f3b7c651e5ce56a'
'1383577e4edacc2d289ec9b25eebfd5e')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 976394
TX_COUNT_HEIGHT = 659520
TX_PER_BLOCK = 2
REORG_LIMIT = 800
RPC_PORT = 3332
PEER_DEFAULT_PORTS = {'t': '53332', 's': '53333'}
PEERS = []
class Litecoin(Coin):
NAME = "Litecoin"
SHORTNAME = "LTC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("30")
P2SH_VERBYTES = (bytes.fromhex("32"), bytes.fromhex("05"))
GENESIS_HASH = ('12a765e31ffd4059bada1e25190f6e98'
'c99d9714d334efa41a195a7e7e04bfe2')
DESERIALIZER = lib_tx.DeserializerLitecoin
TX_COUNT = 8908766
TX_COUNT_HEIGHT = 1105256
TX_PER_BLOCK = 10
RPC_PORT = 9332
REORG_LIMIT = 800
PEERS = [
'ex.lug.gs s444',
'electrum-ltc.bysh.me s t',
'electrum-ltc.ddns.net s t',
'electrum-ltc.wilv.in s t',
'electrum.cryptomachine.com p1000 s t',
'electrum.ltc.xurious.com s t',
]
class LitecoinTestnet(Litecoin):
SHORTNAME = "XLT"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("6f")
P2SH_VERBYTES = (bytes.fromhex("3a"), bytes.fromhex("c4"))
GENESIS_HASH = ('4966625a4b2851d9fdee139e56211a0d'
'88575f59ed816ff5e6a63deb4e3e29a0')
TX_COUNT = 21772
TX_COUNT_HEIGHT = 20800
TX_PER_BLOCK = 2
RPC_PORT = 19332
REORG_LIMIT = 4000
PEER_DEFAULT_PORTS = {'t': '51001', 's': '51002'}
PEERS = [
'electrum-ltc.bysh.me s t',
'electrum.ltc.xurious.com s t',
'ipv6-only.electrum.random.re s t',
]
class LitecoinRegtest(LitecoinTestnet):
NET = "regtest"
GENESIS_HASH = ('530827f38f93b43ed12af0b3ad25a288'
'dc02ed74d6d7857862df51fc56c416f9')
PEERS = []
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
class BitcoinCashRegtest(BitcoinTestnetMixin, Coin):
NAME = "BitcoinCash"
NET = "regtest"
PEERS = []
GENESIS_HASH = ('0f9188f13cb7b2c71f2a335e3a4fc328'
'bf5beb436012afca590b1a11466e2206')
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
BLOCK_PROCESSOR = block_proc.LTORBlockProcessor
class Viacoin(AuxPowMixin, Coin):
NAME = "Viacoin"
SHORTNAME = "VIA"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("47")
P2SH_VERBYTES = (bytes.fromhex("21"),)
GENESIS_HASH = ('4e9b54001f9976049830128ec0331515'
'eaabe35a70970d79971da1539a400ba1')
TX_COUNT = 113638
TX_COUNT_HEIGHT = 3473674
TX_PER_BLOCK = 30
RPC_PORT = 5222
REORG_LIMIT = 5000
DESERIALIZER = lib_tx.DeserializerAuxPowSegWit
PEERS = [
'vialectrum.bitops.me s t',
'server.vialectrum.org s t',
'vialectrum.viacoin.net s t',
'viax1.bitops.me s t',
]
class ViacoinTestnet(Viacoin):
SHORTNAME = "TVI"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("7f")
P2SH_VERBYTES = (bytes.fromhex("c4"),)
GENESIS_HASH = ('00000007199508e34a9ff81e6ec0c477'
'a4cccff2a4767a8eee39c11db367b008')
RPC_PORT = 25222
REORG_LIMIT = 2500
PEER_DEFAULT_PORTS = {'t': '51001', 's': '51002'}
PEERS = [
'vialectrum.bysh.me s t',
]
class ViacoinTestnetSegWit(ViacoinTestnet):
NET = "testnet-segwit"
DESERIALIZER = lib_tx.DeserializerSegWit
# Source: https://github.com/GravityCoinOfficial/GravityCoin/
class GravityCoin(Coin):
NAME = "GravityCoin"
SHORTNAME = "GXX"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("28")
P2SH_VERBYTES = (bytes.fromhex("0a"),)
GENESIS_HASH = '322bad477efb4b33fa4b1f0b2861eaf543c61068da9898a95062fdb02ada486f'
TX_COUNT = 446050
TX_COUNT_HEIGHT = 547346
TX_PER_BLOCK = 2
PEER_DEFAULT_PORTS = {'t': '50001', 's': '50002'}
RPC_PORT = 29200
REORG_LIMIT = 5000
PEERS = []
# Source: https://github.com/BitcoinZeroOfficial/bitcoinzero
class Bitcoinzero(Coin):
NAME = "Bitcoinzero"
SHORTNAME = "BZX"
TX_COUNT = 43798
TX_COUNT_HEIGHT = 44
TX_PER_BLOCK = 576
NET = "mainnet"
GENESIS_HASH = '322bad477efb4b33fa4b1f0b2861eaf543c61068da9898a95062fdb02ada486f'
P2PKH_VERBYTE = bytes.fromhex("4b")
P2SH_VERBYTES = (bytes.fromhex("22"),)
RPC_PORT = 29202
REORG_LIMIT = 5000
PEERS = []
class Unitus(Coin):
NAME = "Unitus"
SHORTNAME = "UIS"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("44")
P2SH_VERBYTES = (bytes.fromhex("0A"),)
GENESIS_HASH = ('d8a2b2439d013a59f3bfc626a33487a3'
'd7d27e42a3c9e0b81af814cd8e592f31')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 3484561
TX_COUNT_HEIGHT = 1697605
TX_PER_BLOCK = 3
RPC_PORT = 50604
REORG_LIMIT = 2000
PEERS = [
'electrumx.unituscurrency.com s t',
]
# Source: namecoin.org
class Namecoin(NameIndexAuxPoWMixin, Coin):
NAME = "Namecoin"
SHORTNAME = "NMC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("34")
P2SH_VERBYTES = (bytes.fromhex("0d"),)
GENESIS_HASH = ('000000000062b72c5e2ceb45fbc8587e'
'807c155b0da735e6483dfba2f0a9c770')
DESERIALIZER = lib_tx.DeserializerAuxPowSegWit
TX_COUNT = 4415768
TX_COUNT_HEIGHT = 329065
TX_PER_BLOCK = 10
RPC_PORT = 8336
PEERS = [
'198.50.223.25 s50002',
'46.229.238.187 s57002',
'198.50.223.27 s50002',
'electrum-nmc.le-space.de s50002',
'electrumx2.nmc.dotbit.zone s50002',
'electrumx4.nmc.dotbit.zone s50002',
'nmc.bitcoins.sk s50002',
'nmc2.bitcoins.sk s57002',
'ulrichard.ch s50006 t50005',
'h6qrnwxtwiaahsw4qhk2nbutswwb54vnqso6jrxeuk6nwtfbos7jkoqd.onion s50002',
'mqhok2edqcxdpklwovquuvvl2q5or4g2o777qwrinydgzfxjbixq76yd.onion s50002',
'wirg2tsto7rme7n26lkd3ivbvxmjyy2pktlozwjuep22jcsfsghfqbqd.onion s50002',
'quuzpffsddq3aim3gk4oiczzyt5okjjzf4zpe6okzo6qidao6rshynqd.onion s50002',
]
BLOCK_PROCESSOR = block_proc.NameIndexBlockProcessor
NAME_EXPIRATION = 36_000
# Name opcodes
OP_NAME_NEW = OpCodes.OP_1
OP_NAME_FIRSTUPDATE = OpCodes.OP_2
OP_NAME_UPDATE = OpCodes.OP_3
# Valid name prefixes.
NAME_NEW_OPS = [OP_NAME_NEW, -1, OpCodes.OP_2DROP]
NAME_FIRSTUPDATE_OPS = [OP_NAME_FIRSTUPDATE, "name", -1, -1,
OpCodes.OP_2DROP, OpCodes.OP_2DROP]
NAME_UPDATE_OPS = [OP_NAME_UPDATE, "name", -1, OpCodes.OP_2DROP,
OpCodes.OP_DROP]
NAME_OPERATIONS = (
NAME_NEW_OPS,
NAME_FIRSTUPDATE_OPS,
NAME_UPDATE_OPS,
)
class NamecoinTestnet(Namecoin):
NAME = "Namecoin"
SHORTNAME = "XNM"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("6f")
P2SH_VERBYTES = (bytes.fromhex("c4"),)
GENESIS_HASH = ('00000007199508e34a9ff81e6ec0c477'
'a4cccff2a4767a8eee39c11db367b008')
class NamecoinRegtest(NamecoinTestnet):
NAME = "Namecoin"
NET = "regtest"
GENESIS_HASH = ('0f9188f13cb7b2c71f2a335e3a4fc328'
'bf5beb436012afca590b1a11466e2206')
PEERS = []
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
NAME_EXPIRATION = 30
class Dogecoin(AuxPowMixin, Coin):
NAME = "Dogecoin"
SHORTNAME = "DOGE"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1e")
P2SH_VERBYTES = (bytes.fromhex("16"),)
GENESIS_HASH = ('1a91e3dace36e2be3bf030a65679fe82'
'1aa1d6ef92e7c9902eb318182c355691')
TX_COUNT = 27583427
TX_COUNT_HEIGHT = 1604979
TX_PER_BLOCK = 20
REORG_LIMIT = 2000
DESERIALIZER = lib_tx.DeserializerAuxPowSegWit
class DogecoinTestnet(Dogecoin):
NAME = "Dogecoin"
SHORTNAME = "XDT"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("71")
P2SH_VERBYTES = (bytes.fromhex("c4"),)
GENESIS_HASH = ('bb0a78264637406b6360aad926284d54'
'4d7049f45189db5664f3c4d07350559e')
# Source: https://github.com/dashpay/dash
class Dash(Coin):
NAME = "Dash"
SHORTNAME = "DASH"
NET = "mainnet"
GENESIS_HASH = ('00000ffd590b1485b3caadc19b22e637'
'9c733355108f107a430458cdf3407ab6')
P2PKH_VERBYTE = bytes.fromhex("4c")
P2SH_VERBYTES = (bytes.fromhex("10"),)
TX_COUNT_HEIGHT = 569399
TX_COUNT = 2157510
TX_PER_BLOCK = 4
RPC_PORT = 9998
PEERS = [
'electrum.dash.org s t',
'electrum.masternode.io s t',
'electrum-drk.club s t',
'dashcrypto.space s t',
'electrum.dash.siampm.com s t',
]
SESSIONCLS = DashElectrumX
DAEMON = daemon.DashDaemon
DESERIALIZER = lib_tx_dash.DeserializerDash
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
import dash_hash
return dash_hash.getPoWHash(header)
class DashTestnet(Dash):
SHORTNAME = "tDASH"
NET = "testnet"
GENESIS_HASH = ('00000bafbc94add76cb75e2ec9289483'
'7288a481e5c005f6563d91623bf8bc2c')
P2PKH_VERBYTE = bytes.fromhex("8c")
P2SH_VERBYTES = (bytes.fromhex("13"),)
TX_COUNT_HEIGHT = 101619
TX_COUNT = 132681
TX_PER_BLOCK = 1
RPC_PORT = 19998
PEER_DEFAULT_PORTS = {'t': '51001', 's': '51002'}
PEERS = [
'electrum.dash.siampm.com s t',
'dasht.random.re s54002 t54001',
]
class DashRegtest(DashTestnet):
NET = "regtest"
GENESIS_HASH = ('000008ca1832a4baf228eb1553c03d3a'
'2c8e02399550dd6ea8d65cec3ef23d2e')
PEERS = []
TX_COUNT_HEIGHT = 1
TX_COUNT = 1
class Argentum(AuxPowMixin, Coin):
NAME = "Argentum"
SHORTNAME = "ARG"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("17")
GENESIS_HASH = ('88c667bc63167685e4e4da058fffdfe8'
'e007e5abffd6855de52ad59df7bb0bb2')
TX_COUNT = 2263089
TX_COUNT_HEIGHT = 2050260
TX_PER_BLOCK = 2000
RPC_PORT = 13581
class ArgentumTestnet(Argentum):
SHORTNAME = "XRG"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("6f")
P2SH_VERBYTES = (bytes.fromhex("c4"),)
REORG_LIMIT = 2000
class DigiByte(Coin):
NAME = "DigiByte"
SHORTNAME = "DGB"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1E")
GENESIS_HASH = ('7497ea1b465eb39f1c8f507bc877078f'
'e016d6fcb6dfad3a64c98dcc6e1e8496')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 1046018
TX_COUNT_HEIGHT = 1435000
TX_PER_BLOCK = 1000
RPC_PORT = 12022
class DigiByteTestnet(DigiByte):
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("6f")
P2SH_VERBYTES = (bytes.fromhex("c4"),)
GENESIS_HASH = ('b5dca8039e300198e5fe7cd23bdd1728'
'e2a444af34c447dbd0916fa3430a68c2')
RPC_PORT = 15022
REORG_LIMIT = 2000
class FairCoin(Coin):
NAME = "FairCoin"
SHORTNAME = "FAIR"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("5f")
P2SH_VERBYTES = (bytes.fromhex("24"),)
GENESIS_HASH = ('beed44fa5e96150d95d56ebd5d262578'
'1825a9407a5215dd7eda723373a0a1d7')
BASIC_HEADER_SIZE = 108
TX_COUNT = 505
TX_COUNT_HEIGHT = 470
TX_PER_BLOCK = 1
RPC_PORT = 40405
PEER_DEFAULT_PORTS = {'t': '51811', 's': '51812'}
PEERS = [
'electrum.faircoin.world s',
'electrumfair.punto0.org s',
]
@classmethod
def block(cls, raw_block, height):
'''Return a Block given a raw block and its height.'''
if height > 0:
return super().block(raw_block, height)
else:
return Block(raw_block, cls.block_header(raw_block, height), [])
class Zcash(EquihashMixin, Coin):
NAME = "Zcash"
SHORTNAME = "ZEC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1CB8")
P2SH_VERBYTES = (bytes.fromhex("1CBD"),)
GENESIS_HASH = ('00040fe8ec8471911baa1db1266ea15d'
'd06b4a8a5c453883c000b031973dce08')
DESERIALIZER = lib_tx.DeserializerZcash
TX_COUNT = 329196
TX_COUNT_HEIGHT = 68379
TX_PER_BLOCK = 5
RPC_PORT = 8232
REORG_LIMIT = 800
class ZcashTestnet(Zcash):
SHORTNAME = "TAZ"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("1D25")
P2SH_VERBYTES = (bytes.fromhex("1CBA"),)
GENESIS_HASH = ('05a60a92d99d85997cce3b87616c089f'
'6124d7342af37106edc76126334a2c38')
TX_COUNT = 242312
TX_COUNT_HEIGHT = 321685
TX_PER_BLOCK = 2
RPC_PORT = 18232
class SnowGem(EquihashMixin, Coin):
NAME = "SnowGem"
SHORTNAME = "XSG"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1C28")
P2SH_VERBYTES = (bytes.fromhex("1C2D"),)
GENESIS_HASH = ('00068b35729d9d2b0c294ff1fe9af009'
'4740524311a131de40e7f705e4c29a5b')
DESERIALIZER = lib_tx.DeserializerZcash
TX_COUNT = 1680878
TX_COUNT_HEIGHT = 627250
TX_PER_BLOCK = 2
RPC_PORT = 16112
REORG_LIMIT = 800
CHUNK_SIZE = 200
class Zero(EquihashMixin, Coin):
NAME = "Zero"
SHORTNAME = "ZER"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1CB8")
P2SH_VERBYTES = (bytes.fromhex("1CBD"),)
GENESIS_HASH = ('068cbb5db6bc11be5b93479ea4df41fa'
'7e012e92ca8603c315f9b1a2202205c6')
DESERIALIZER = lib_tx.DeserializerZcash
TX_COUNT = 329998
TX_COUNT_HEIGHT = 847425
TX_PER_BLOCK = 2
RPC_PORT = 23811
REORG_LIMIT = 800
class BitcoinZ(EquihashMixin, Coin):
NAME = "BitcoinZ"
SHORTNAME = "BTCZ"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1CB8")
P2SH_VERBYTES = (bytes.fromhex("1CBD"),)
GENESIS_HASH = ('f499ee3d498b4298ac6a64205b8addb7'
'c43197e2a660229be65db8a4534d75c1')
DESERIALIZER = lib_tx.DeserializerZcash
TX_COUNT = 171976
TX_COUNT_HEIGHT = 81323
TX_PER_BLOCK = 3
RPC_PORT = 1979
REORG_LIMIT = 800
class ZelCash(EquihashMixin, Coin):
NAME = "ZelCash"
SHORTNAME = "ZEL"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1CB8")
P2SH_VERBYTES = (bytes.fromhex("1CBD"),)
GENESIS_HASH = ('00052461a5006c2e3b74ce48992a0869'
'5607912d5604c3eb8da25749b0900444')
DESERIALIZER = lib_tx.DeserializerZcash
TX_COUNT = 450539
TX_COUNT_HEIGHT = 167114
TX_PER_BLOCK = 3
RPC_PORT = 16124
REORG_LIMIT = 800
class Zclassic(EquihashMixin, Coin):
NAME = "Zclassic"
SHORTNAME = "ZCL"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1CB8")
P2SH_VERBYTES = (bytes.fromhex("1CBD"),)
GENESIS_HASH = ('0007104ccda289427919efc39dc9e4d4'
'99804b7bebc22df55f8b834301260602')
DESERIALIZER = lib_tx.DeserializerZcash
TX_COUNT = 329196
TX_COUNT_HEIGHT = 68379
TX_PER_BLOCK = 5
RPC_PORT = 8023
REORG_LIMIT = 800
class Koto(Coin):
NAME = "Koto"
SHORTNAME = "KOTO"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1836")
P2SH_VERBYTES = (bytes.fromhex("183B"),)
GENESIS_HASH = ('6d424c350729ae633275d51dc3496e16'
'cd1b1d195c164da00f39c499a2e9959e')
DESERIALIZER = lib_tx.DeserializerZcash
TX_COUNT = 158914
TX_COUNT_HEIGHT = 67574
TX_PER_BLOCK = 3
RPC_PORT = 8432
REORG_LIMIT = 800
PEERS = [
'fr.kotocoin.info s t',
'electrum.kotocoin.info s t',
]
class KotoTestnet(Koto):
SHORTNAME = "TOKO"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("18A4")
P2SH_VERBYTES = (bytes.fromhex("1839"),)
GENESIS_HASH = ('bf84afbde20c2d213b68b231ddb585ab'
'616ef7567226820f00d9b397d774d2f0')
TX_COUNT = 91144
TX_COUNT_HEIGHT = 89662
TX_PER_BLOCK = 1
RPC_PORT = 18432
PEER_DEFAULT_PORTS = {'t': '51001', 's': '51002'}
PEERS = [
'testnet.kotocoin.info s t',
]
class Komodo(KomodoMixin, EquihashMixin, Coin):
NAME = "Komodo"
SHORTNAME = "KMD"
NET = "mainnet"
TX_COUNT = 693629
TX_COUNT_HEIGHT = 491777
TX_PER_BLOCK = 2
RPC_PORT = 7771
REORG_LIMIT = 800
PEERS = []
class Hush(KomodoMixin, EquihashMixin, Coin):
NAME = "Hush"
SHORTNAME = "HUSH"
NET = "mainnet"
TX_COUNT = 111317
TX_COUNT_HEIGHT = 169280
TX_PER_BLOCK = 2
RPC_PORT = 18031
REORG_LIMIT = 800
class Monaize(KomodoMixin, EquihashMixin, Coin):
NAME = "Monaize"
SHORTNAME = "MNZ"
NET = "mainnet"
TX_COUNT = 256
TX_COUNT_HEIGHT = 128
TX_PER_BLOCK = 2
RPC_PORT = 14337
REORG_LIMIT = 800
PEERS = []
class Einsteinium(Coin):
NAME = "Einsteinium"
SHORTNAME = "EMC2"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("21")
GENESIS_HASH = ('4e56204bb7b8ac06f860ff1c845f03f9'
'84303b5b97eb7b42868f714611aed94b')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 2087559
TX_COUNT_HEIGHT = 1358517
TX_PER_BLOCK = 2
RPC_PORT = 41879
REORG_LIMIT = 2000
class Blackcoin(ScryptMixin, Coin):
NAME = "Blackcoin"
SHORTNAME = "BLK"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("19")
P2SH_VERBYTES = (bytes.fromhex("55"),)
GENESIS_HASH = ('000001faef25dec4fbcf906e6242621d'
'f2c183bf232f263d0ba5b101911e4563')
DESERIALIZER = lib_tx.DeserializerBlackcoin
DAEMON = daemon.FakeEstimateFeeDaemon
TX_COUNT = 10802426
TX_COUNT_HEIGHT = 3431329
TX_PER_BLOCK = 3
RPC_PORT = 15715
REORG_LIMIT = 500
ESTIMATE_FEE = 0.0001
RELAY_FEE = 0.0001
PEERS = [
'electrum1.blackcoin.nl t10001 s10002',
'electrum2.blackcoin.nl t20001 s20002',
'electrum3.blackcoin.nl t30001 s30002',
]
class BlackcoinTestnet(Blackcoin):
NAME = "BlackcoinTestnet"
SHORTNAME = "tBLK"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("6F")
P2SH_VERBYTES = (bytes.fromhex("C4"),)
GENESIS_HASH = ('0000724595fb3b9609d441cbfb957761'
'5c292abf07d996d3edabc48de843642d')
DESERIALIZER = lib_tx.DeserializerBlackcoin
DAEMON = daemon.FakeEstimateFeeDaemon
TX_COUNT = 1401229
TX_COUNT_HEIGHT = 698611
TX_PER_BLOCK = 2
RPC_PORT = 25715
REORG_LIMIT = 500
ESTIMATE_FEE = 0.001
RELAY_FEE = 0.001
PEERS = [
'electrum1.blackcoin.nl t10011 s10012',
'electrum2.blackcoin.nl t20011 s20012',
'electrum3.blackcoin.nl t30011 s30012',
]
class Bitbay(ScryptMixin, Coin):
NAME = "Bitbay"
SHORTNAME = "BAY"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("19")
P2SH_VERBYTES = (bytes.fromhex("55"),)
GENESIS_HASH = ('0000075685d3be1f253ce777174b1594'
'354e79954d2a32a6f77fe9cba00e6467')
TX_COUNT = 4594999
TX_COUNT_HEIGHT = 1667070
TX_PER_BLOCK = 3
RPC_PORT = 19914
REORG_LIMIT = 5000
class DeepOnion(Coin):
NAME = "DeepOnion"
SHORTNAME = "ONION"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1F")
P2SH_VERBYTES = (bytes.fromhex("4E"),)
GENESIS_HASH = ('000004e29458ef4f2e0abab544737b07'
'344e6ff13718f7c2d12926166db07b5e')
DESERIALIZER = lib_tx.DeserializerTxTime
DAEMON = daemon.LegacyRPCDaemon
TX_COUNT = 1194707
TX_COUNT_HEIGHT = 530000
TX_PER_BLOCK = 2
RPC_PORT = 18580
REORG_LIMIT = 200
PEERS = []
@classmethod
def header_hash_rev(cls, header):
'''
Given a header return the hash for DeepOnion.
Need to download `x13_hash` module
Source code: https://github.com/MaruCoinOfficial/x13-hash
'''
import x13_hash
return x13_hash.getPoWHash(header)
class Peercoin(Coin):
NAME = "Peercoin"
SHORTNAME = "PPC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("37")
P2SH_VERBYTES = (bytes.fromhex("75"),)
GENESIS_HASH = ('0000000032fe677166d54963b62a4677'
'd8957e87c508eaa4fd7eb1c880cd27e3')
DESERIALIZER = lib_tx.DeserializerTxTimeSegWit
DAEMON = daemon.FakeEstimateFeeDaemon
ESTIMATE_FEE = 0.001
RELAY_FEE = 0.01
TX_COUNT = 1691771
TX_COUNT_HEIGHT = 455409
TX_PER_BLOCK = 4
RPC_PORT = 9902
REORG_LIMIT = 5000
PEERS = [
"electrum.peercoinexplorer.net s",
]
VALUE_PER_COIN = 1000000
class PeercoinTestnet(Peercoin):
NAME = "PeercoinTestnet"
SHORTNAME = "tPPC"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("6f")
P2SH_VERBYTES = (bytes.fromhex("c4"),)
GENESIS_HASH = ('00000001f757bb737f6596503e17cd17'
'b0658ce630cc727c0cca81aec47c9f06')
ESTIMATE_FEE = 0.001
PEERS = [
"testnet-electrum.peercoinexplorer.net s",
]
class Trezarcoin(Coin):
NAME = "Trezarcoin"
SHORTNAME = "TZC"
NET = "mainnet"
VALUE_PER_COIN = 1000000
P2PKH_VERBYTE = bytes.fromhex("42")
P2SH_VERBYTES = (bytes.fromhex("08"),)
GENESIS_HASH = ('24502ba55d673d2ee9170d83dae2d1ad'
'b3bfb4718e4f200db9951382cc4f6ee6')
DESERIALIZER = lib_tx.DeserializerTrezarcoin
HEADER_HASH = lib_tx.DeserializerTrezarcoin.blake2s
HEADER_HASH_GEN = lib_tx.DeserializerTrezarcoin.blake2s_gen
BASIC_HEADER_SIZE = 80
TX_COUNT = 742886
TX_COUNT_HEIGHT = 643128
TX_PER_BLOCK = 2
RPC_PORT = 17299
REORG_LIMIT = 2000
PEERS = [
'electrumx1.trezarcoin.com s t',
]
@classmethod
def genesis_block(cls, block):
'''Check the Genesis block is the right one for this coin.
Return the block less its unspendable coinbase.
'''
header = cls.block_header(block, 0)
header_hex_hash = cls.HEADER_HASH_GEN(header)
if header_hex_hash != cls.GENESIS_HASH:
raise CoinError(f'genesis block has hash {header_hex_hash} '
f'expected {cls.GENESIS_HASH}')
return header + b'\0'
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
return cls.HEADER_HASH(header)
class Reddcoin(Coin):
NAME = "Reddcoin"
SHORTNAME = "RDD"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("3d")
GENESIS_HASH = ('b868e0d95a3c3c0e0dadc67ee587aaf9'
'dc8acbf99e3b4b3110fad4eb74c1decc')
DESERIALIZER = lib_tx.DeserializerReddcoin
TX_COUNT = 5413508
TX_COUNT_HEIGHT = 1717382
TX_PER_BLOCK = 3
RPC_PORT = 45443
class TokenPay(ScryptMixin, Coin):
NAME = "TokenPay"
SHORTNAME = "TPAY"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("41")
P2SH_VERBYTES = (bytes.fromhex("7e"),)
GENESIS_HASH = ('000008b71ab32e585a23f0de642dc113'
'740144e94c0ece047751e9781f953ae9')
DESERIALIZER = lib_tx.DeserializerTokenPay
DAEMON = daemon.LegacyRPCDaemon
TX_COUNT = 147934
TX_COUNT_HEIGHT = 73967
TX_PER_BLOCK = 100
RPC_PORT = 8800
REORG_LIMIT = 500
PEERS = [
"electrum-us.tpay.ai s",
"electrum-eu.tpay.ai s",
]
class Vertcoin(Coin):
NAME = "Vertcoin"
SHORTNAME = "VTC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("47")
GENESIS_HASH = ('4d96a915f49d40b1e5c2844d1ee2dccb'
'90013a990ccea12c492d22110489f0c4')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 2383423
TX_COUNT_HEIGHT = 759076
TX_PER_BLOCK = 3
RPC_PORT = 5888
REORG_LIMIT = 1000
PEERS = [
'electrumx-vtc.cryptoverted.com t55001 s55002',
'electrumx.javerity.com t5885 s5886',
]
class VertcoinTestnet(Vertcoin):
SHORTNAME = "TVTC"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("4a")
P2SH_VERBYTES = (bytes.fromhex("c4"),)
GENESIS_HASH = ('cee8f24feb7a64c8f07916976aa4855d'
'ecac79b6741a8ec2e32e2747497ad2c9')
RPC_PORT = 15888
PEERS = [
'electrumx-tvtc.javerity.com t15885 s15886',
]
class Monacoin(Coin):
NAME = "Monacoin"
SHORTNAME = "MONA"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("32")
P2SH_VERBYTES = (bytes.fromhex("37"), bytes.fromhex("05"))
GENESIS_HASH = ('ff9f1c0116d19de7c9963845e129f9ed'
'1bfc0b376eb54fd7afa42e0d418c8bb6')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 2568580
TX_COUNT_HEIGHT = 1029766
TX_PER_BLOCK = 2
RPC_PORT = 9402
REORG_LIMIT = 1000
BLACKLIST_URL = 'https://electrum-mona.org/blacklist.json'
PEERS = [
'electrumx.tamami-foundation.org s t',
'electrumx3.monacoin.nl s t',
'electrumx1.monacoin.ninja s t',
'electrumx2.movsign.info s t',
'electrum-mona.bitbank.cc s t',
]
class MonacoinTestnet(Monacoin):
SHORTNAME = "XMN"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("6F")
P2SH_VERBYTES = (bytes.fromhex("75"), bytes.fromhex("C4"))
GENESIS_HASH = ('a2b106ceba3be0c6d097b2a6a6aacf9d'
'638ba8258ae478158f449c321061e0b2')
TX_COUNT = 83602
TX_COUNT_HEIGHT = 83252
TX_PER_BLOCK = 1
RPC_PORT = 19402
REORG_LIMIT = 1000
PEER_DEFAULT_PORTS = {'t': '51001', 's': '51002'}
PEERS = [
'electrumx1.testnet.monacoin.ninja s t',
'electrumx1.testnet.monacoin.nl s t',
]
class MonacoinRegtest(MonacoinTestnet):
NET = "regtest"
GENESIS_HASH = ('7543a69d7c2fcdb29a5ebec2fc064c07'
'4a35253b6f3072c8a749473aa590a29c')
PEERS = []
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
class Crown(AuxPowMixin, Coin):
NAME = "Crown"
SHORTNAME = "CRW"
NET = "mainnet"
P2SH_VERBYTES = (bytes.fromhex("1c"),)
GENESIS_HASH = ('0000000085370d5e122f64f4ab19c686'
'14ff3df78c8d13cb814fd7e69a1dc6da')
TX_COUNT = 13336629
TX_COUNT_HEIGHT = 1268206
TX_PER_BLOCK = 10
RPC_PORT = 9341
REORG_LIMIT = 1000
PEERS = [
'sgp-crwseed.crowndns.info s t',
'blr-crwseed.crowndns.info s t',
'sfo-crwseed.crowndns.info s t',
'nyc-crwseed.crowndns.info s t',
'ams-crwseed.crowndns.info s t',
'tor-crwseed.crowndns.info s t',
'lon-crwseed.crowndns.info s t',
'fra-crwseed.crowndns.info s t',
]
class Fujicoin(Coin):
NAME = "Fujicoin"
SHORTNAME = "FJC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("24")
P2SH_VERBYTES = (bytes.fromhex("10"),)
GENESIS_HASH = ('adb6d9cfd74075e7f91608add4bd2a2e'
'a636f70856183086842667a1597714a0')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 170478
TX_COUNT_HEIGHT = 1521676
TX_PER_BLOCK = 1
RPC_PORT = 3776
REORG_LIMIT = 1000
class Neblio(ScryptMixin, Coin):
NAME = "Neblio"
SHORTNAME = "NEBL"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("35")
P2SH_VERBYTES = (bytes.fromhex("70"),)
GENESIS_HASH = ('7286972be4dbc1463d256049b7471c25'
'2e6557e222cab9be73181d359cd28bcc')
TX_COUNT = 23675
TX_COUNT_HEIGHT = 22785
TX_PER_BLOCK = 1
RPC_PORT = 6326
REORG_LIMIT = 1000
class Bitzeny(Coin):
NAME = "Bitzeny"
SHORTNAME = "ZNY"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("51")
GENESIS_HASH = ('000009f7e55e9e3b4781e22bd87a7cfa'
'4acada9e4340d43ca738bf4e9fb8f5ce')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 1408733
TX_COUNT_HEIGHT = 1015115
TX_PER_BLOCK = 1
RPC_PORT = 9252
REORG_LIMIT = 1000
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
import zny_yespower_0_5
return zny_yespower_0_5.getPoWHash(header)
class CanadaeCoin(AuxPowMixin, Coin):
NAME = "CanadaeCoin"
SHORTNAME = "CDN"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1C")
GENESIS_HASH = ('863626dadaef221e2e2f30ff3dacae44'
'cabdae9e0028058072181b3fb675d94a')
ESTIMATE_FEE = 0.0001
RELAY_FEE = 0.0001
DAEMON = daemon.FakeEstimateFeeDaemon
TX_COUNT = 3455905
TX_COUNT_HEIGHT = 3645419
TX_PER_BLOCK = 1
RPC_PORT = 34330
REORG_LIMIT = 1000
class Denarius(Coin):
NAME = "Denarius"
SHORTNAME = "D"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1E") # Address starts with a D
P2SH_VERBYTES = (bytes.fromhex("5A"),)
GENESIS_HASH = ('00000d5dbbda01621cfc16bbc1f9bf32'
'64d641a5dbf0de89fd0182c2c4828fcd')
DESERIALIZER = lib_tx.DeserializerTxTime
TX_COUNT = 4230
RPC_PORT = 32339
ESTIMATE_FEE = 0.00001
RELAY_FEE = 0.00001
DAEMON = daemon.FakeEstimateFeeDaemon
TX_COUNT_HEIGHT = 306187
TX_PER_BLOCK = 4000
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
import tribushashm
return tribushashm.getPoWHash(header)
class DenariusTestnet(Denarius):
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("12")
P2SH_VERBYTES = (bytes.fromhex("74"),)
GENESIS_HASH = ('000086bfe8264d241f7f8e5393f74778'
'4b8ca2aa98bdd066278d590462a4fdb4')
RPC_PORT = 32338
REORG_LIMIT = 2000
class Sibcoin(Dash):
NAME = "Sibcoin"
SHORTNAME = "SIB"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("3F")
P2SH_VERBYTES = (bytes.fromhex("28"),)
GENESIS_HASH = ('00000c492bf73490420868bc577680bf'
'c4c60116e7e85343bc624787c21efa4c')
DAEMON = daemon.DashDaemon
TX_COUNT = 1000
TX_COUNT_HEIGHT = 10000
TX_PER_BLOCK = 1
RPC_PORT = 1944
REORG_LIMIT = 1000
PEERS = []
@classmethod
def header_hash_rev(cls, header):
'''
Given a header return the hash for sibcoin.
Need to download `x11_gost_hash` module
Source code: https://github.com/ivansib/x11_gost_hash
'''
import x11_gost_hash
return x11_gost_hash.getPoWHash(header)
class SibcoinTestnet(Sibcoin):
SHORTNAME = "tSIB"
NET = "testnet"
GENESIS_HASH = ('00000617791d0e19f524387f67e558b2'
'a928b670b9a3b387ae003ad7f9093017')
RPC_PORT = 11944
class Chips(Coin):
NAME = "Chips"
SHORTNAME = "CHIPS"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("3c")
P2SH_VERBYTES = (bytes.fromhex("55"),)
GENESIS_HASH = ('0000006e75f6aa0efdbf7db03132aa4e'
'4d0c84951537a6f5a7c39a0a9d30e1e7')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 145290
TX_COUNT_HEIGHT = 318637
TX_PER_BLOCK = 2
RPC_PORT = 57776
REORG_LIMIT = 800
class Feathercoin(Coin):
NAME = "Feathercoin"
SHORTNAME = "FTC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("0E")
GENESIS_HASH = ('12a765e31ffd4059bada1e25190f6e98'
'c99d9714d334efa41a195a7e7e04bfe2')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 3170843
TX_COUNT_HEIGHT = 1981777
TX_PER_BLOCK = 2
RPC_PORT = 9337
REORG_LIMIT = 2000
PEERS = [
'electrumx-gb-1.feathercoin.network s t',
'electrumx-gb-2.feathercoin.network s t',
'electrumx-de-1.feathercoin.network s t',
]
class UFO(Coin):
NAME = "UniformFiscalObject"
SHORTNAME = "UFO"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1B")
P2SH_VERBYTES = (bytes.fromhex("44"),)
GENESIS_HASH = ('ba1d39b4928ab03d813d952daf65fb77'
'97fcf538a9c1b8274f4edc8557722d13')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 1608926
TX_COUNT_HEIGHT = 1300154
TX_PER_BLOCK = 2
RPC_PORT = 9888
REORG_LIMIT = 2000
PEERS = [
'electrumx1.ufobject.com s t',
]
class Newyorkcoin(AuxPowMixin, Coin):
NAME = "Newyorkcoin"
SHORTNAME = "NYC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("3c")
P2SH_VERBYTES = (bytes.fromhex("16"),)
GENESIS_HASH = ('5597f25c062a3038c7fd815fe46c67de'
'dfcb3c839fbc8e01ed4044540d08fe48')
TX_COUNT = 5161944
TX_COUNT_HEIGHT = 3948743
TX_PER_BLOCK = 2
REORG_LIMIT = 2000
class NewyorkcoinTestnet(Newyorkcoin):
SHORTNAME = "tNYC"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("71")
P2SH_VERBYTES = (bytes.fromhex("c4"),)
GENESIS_HASH = ('24463e4d3c625b0a9059f309044c2cf0'
'd7e196cf2a6ecce901f24f681be33c8f')
TX_COUNT = 5161944
TX_COUNT_HEIGHT = 3948743
TX_PER_BLOCK = 2
REORG_LIMIT = 2000
class Bitcore(Coin):
NAME = "Bitcore"
SHORTNAME = "BTX"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("03")
P2SH_VERBYTES = (bytes.fromhex("7D"),)
DESERIALIZER = lib_tx.DeserializerSegWit
GENESIS_HASH = ('604148281e5c4b7f2487e5d03cd60d8e'
'6f69411d613f6448034508cea52e9574')
TX_COUNT = 126979
TX_COUNT_HEIGHT = 126946
TX_PER_BLOCK = 2
RPC_PORT = 8556
PEERS = [
'ele1.bitcore.cc s t',
'ele2.bitcore.cc s t',
'ele3.bitcore.cc s t',
'ele4.bitcore.cc s t',
]
class GameCredits(Coin):
NAME = "GameCredits"
SHORTNAME = "GAME"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("26")
GENESIS_HASH = ('91ec5f25ee9a0ffa1af7d4da4db9a552'
'228dd2dc77cdb15b738be4e1f55f30ee')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 316796
TX_COUNT_HEIGHT = 2040250
TX_PER_BLOCK = 2
RPC_PORT = 40001
REORG_LIMIT = 1000
class Machinecoin(Coin):
NAME = "Machinecoin"
SHORTNAME = "MAC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("32")
P2SH_VERBYTES = (bytes.fromhex("26"), bytes.fromhex("05"))
GENESIS_HASH = ('6a1f879bcea5471cbfdee1fd0cb2ddcc'
'4fed569a500e352d41de967703e83172')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 137641
TX_COUNT_HEIGHT = 513020
TX_PER_BLOCK = 2
RPC_PORT = 40332
REORG_LIMIT = 800
class BitcoinAtom(Coin):
NAME = "BitcoinAtom"
SHORTNAME = "BCA"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("17")
P2SH_VERBYTES = (bytes.fromhex("0a"),)
STATIC_BLOCK_HEADERS = False
DESERIALIZER = lib_tx.DeserializerBitcoinAtom
HEADER_SIZE_POST_FORK = 84
BLOCK_PROOF_OF_STAKE = 0x01
BLOCK_PROOF_OF_STAKE_FLAGS = b'\x01\x00\x00\x00'
TX_COUNT = 295158744
TX_COUNT_HEIGHT = 589197
TX_PER_BLOCK = 10
RPC_PORT = 9136
REORG_LIMIT = 5000
@classmethod
def header_hash_rev(cls, header):
'''Given a header return hash'''
header_to_be_hashed = header[:cls.BASIC_HEADER_SIZE]
# New block header format has some extra flags in the end
if len(header) == cls.HEADER_SIZE_POST_FORK:
flags, = util.unpack_le_uint32_from(header, len(header) - 4)
# Proof of work blocks have special serialization
if flags & cls.BLOCK_PROOF_OF_STAKE != 0:
header_to_be_hashed += cls.BLOCK_PROOF_OF_STAKE_FLAGS
return double_sha256(header_to_be_hashed)
@classmethod
def block_header(cls, block, height):
'''Return the block header bytes'''
deserializer = cls.DESERIALIZER(block)
return deserializer.read_header(height, cls.BASIC_HEADER_SIZE)
class Decred(Coin):
NAME = "Decred"
SHORTNAME = "DCR"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("073f")
P2SH_VERBYTES = (bytes.fromhex("071a"),)
GENESIS_HASH = ('298e5cc3d985bfe7f81dc135f360abe0'
'89edd4396b86d2de66b0cef42b21d980')
BASIC_HEADER_SIZE = 180
HEADER_HASH = lib_tx.DeserializerDecred.blake256
DESERIALIZER = lib_tx.DeserializerDecred
DAEMON = daemon.DecredDaemon
BLOCK_PROCESSOR = block_proc.DecredBlockProcessor
ENCODE_CHECK = partial(Base58.encode_check,
hash_fn=lib_tx.DeserializerDecred.blake256d)
DECODE_CHECK = partial(Base58.decode_check,
hash_fn=lib_tx.DeserializerDecred.blake256d)
TX_COUNT = 4629388
TX_COUNT_HEIGHT = 260628
TX_PER_BLOCK = 17
REORG_LIMIT = 1000
RPC_PORT = 9109
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
return cls.HEADER_HASH(header)
@classmethod
def block(cls, raw_block, height):
'''Return a Block namedtuple given a raw block and its height.'''
if height > 0:
return super().block(raw_block, height)
else:
return Block(raw_block, cls.block_header(raw_block, height), [])
class DecredTestnet(Decred):
SHORTNAME = "tDCR"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("0f21")
P2SH_VERBYTES = (bytes.fromhex("0efc"),)
GENESIS_HASH = (
'a649dce53918caf422e9c711c858837e08d626ecfcd198969b24f7b634a49bac')
BASIC_HEADER_SIZE = 180
TX_COUNT = 217380620
TX_COUNT_HEIGHT = 464000
TX_PER_BLOCK = 1800
REORG_LIMIT = 1000
RPC_PORT = 19109
class Axe(Dash):
NAME = "Axe"
SHORTNAME = "AXE"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("37")
P2SH_VERBYTES = (bytes.fromhex("10"),)
GENESIS_HASH = ('00000c33631ca6f2f61368991ce2dc03'
'306b5bb50bf7cede5cfbba6db38e52e6')
SESSIONCLS = DashElectrumX
DAEMON = daemon.DashDaemon
DESERIALIZER = lib_tx_axe.DeserializerAxe
TX_COUNT = 18405
TX_COUNT_HEIGHT = 30237
TX_PER_BLOCK = 1
RPC_PORT = 9337
REORG_LIMIT = 1000
PEERS = []
@classmethod
def header_hash_rev(cls, header):
'''
Given a header return the hash for AXE.
Need to download `axe_hash` module
Source code: https://github.com/AXErunners/axe_hash
'''
import dash_hash
return dash_hash.getPoWHash(header)
class AxeTestnet(Axe):
SHORTNAME = "tAxe"
NET = "testnet"
GENESIS_HASH = ('000005b709662e7bc5e89c71d3aba6c9'
'd4623b4bbf44ac205caec55f4cefb483')
P2PKH_VERBYTE = bytes.fromhex("8c")
P2SH_VERBYTES = (bytes.fromhex("13"),)
TX_COUNT_HEIGHT = 101619
TX_COUNT = 132681
TX_PER_BLOCK = 1
RPC_PORT = 19937
PEER_DEFAULT_PORTS = {'t': '51001', 's': '51002'}
PEERS = []
class AxeRegtest(AxeTestnet):
NET = "regtest"
GENESIS_HASH = ('2026b8850f3774a0536152ba868c4dcb'
'de9aef5ffc28a5d23f76f80e9b46e565')
PEERS = []
TX_COUNT_HEIGHT = 1
RPC_PORT = 19869
TX_COUNT = 1
class Xuez(Coin):
NAME = "Xuez"
SHORTNAME = "XUEZ"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("48")
P2SH_VERBYTES = (bytes.fromhex("12"),)
GENESIS_HASH = ('000000e1febc39965b055e8e0117179a'
'4d18e24e7aaa0c69864c4054b4f29445')
TX_COUNT = 30000
TX_COUNT_HEIGHT = 15000
TX_PER_BLOCK = 1
RPC_PORT = 41799
REORG_LIMIT = 1000
BASIC_HEADER_SIZE = 112
PEERS = []
@classmethod
def header_hash_rev(cls, header):
'''
Given a header return the hash for Xuez.
Need to download `xevan_hash` module
Source code: https://github.com/xuez/xuez
'''
version, = util.unpack_le_uint32_from(header)
import xevan_hash
if version == 1:
return xevan_hash.getPoWHash(header[:80])
else:
return xevan_hash.getPoWHash(header)
# Source: https://github.com/odinblockchain/odin
class Odin(Coin):
NAME = "ODIN"
SHORTNAME = "ODIN"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("73")
P2SH_VERBYTES = (bytes.fromhex("39"),)
GENESIS_HASH = ('31ca29566549e444cf227a0e2e067aed'
'847c2acc541d3bbf9ca1ae89f4fd57d7')
TX_COUNT = 340000
TX_COUNT_HEIGHT = 340000
TX_PER_BLOCK = 2
RPC_PORT = 22101
REORG_LIMIT = 100
BASIC_HEADER_SIZE = 80
HDR_V4_SIZE = 112
HDR_V4_HEIGHT = 143447
HDR_V4_START_OFFSET = HDR_V4_HEIGHT * BASIC_HEADER_SIZE
SESSIONCLS = DashElectrumX
DAEMON = daemon.DashDaemon
DESERIALIZER = lib_tx.DeserializerSegWit
@classmethod
def static_header_offset(cls, height):
assert cls.STATIC_BLOCK_HEADERS
if height >= cls.HDR_V4_HEIGHT:
relative_v4_offset = (height - cls.HDR_V4_HEIGHT) * cls.HDR_V4_SIZE
return cls.HDR_V4_START_OFFSET + relative_v4_offset
else:
return height * cls.BASIC_HEADER_SIZE
@classmethod
def header_hash_rev(cls, header):
version, = util.unpack_le_uint32_from(header)
if version >= 4:
return super().header_hash_rev(header)
else:
import quark_hash
return quark_hash.getPoWHash(header)
class Pac(Coin):
NAME = "PAC"
SHORTNAME = "PAC"
NET = "mainnet"
GENESIS_HASH = ('00000354655ff039a51273fe61d3b493'
'bd2897fe6c16f732dbc4ae19f04b789e')
P2PKH_VERBYTE = bytes.fromhex("37")
P2SH_VERBYTES = (bytes.fromhex("0A"),)
TX_COUNT_HEIGHT = 14939
TX_COUNT = 23708
TX_PER_BLOCK = 2
RPC_PORT = 7111
PEERS = [
'electrum.paccoin.io s t',
'electro-pac.paccoin.io s t',
]
SESSIONCLS = DashElectrumX
DAEMON = daemon.DashDaemon
ESTIMATE_FEE = 0.00001
RELAY_FEE = 0.00001
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
import dash_hash
return dash_hash.getPoWHash(header)
class PacTestnet(Pac):
SHORTNAME = "tPAC"
NET = "testnet"
GENESIS_HASH = ('00000da63bd9478b655ef6bf1bf76cd9'
'af05202ab68643f9091e049b2b5280ed')
P2PKH_VERBYTE = bytes.fromhex("78")
P2SH_VERBYTES = (bytes.fromhex("0E"),)
TX_COUNT_HEIGHT = 16275
TX_COUNT = 16275
TX_PER_BLOCK = 1
RPC_PORT = 17111
class Zcoin(Coin):
NAME = "Zcoin"
SHORTNAME = "XZC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("52")
P2SH_VERBYTES = (bytes.fromhex("07"),)
GENESIS_HASH = ('4381deb85b1b2c9843c222944b616d99'
'7516dcbd6a964e1eaf0def0830695233')
TX_COUNT = 667154
TX_COUNT_HEIGHT = 100266
TX_PER_BLOCK = 4000 # 2000 for 1MB block
RPC_PORT = 8888
REORG_LIMIT = 5000
PEER_DEFAULT_PORTS = {'t': '50001', 's': '50002'}
MTP_HEADER_EXTRA_SIZE = 100
MTP_HEADER_DATA_SIZE = 198864
MTP_HEADER_DATA_START = Coin.BASIC_HEADER_SIZE + MTP_HEADER_EXTRA_SIZE
MTP_HEADER_DATA_END = MTP_HEADER_DATA_START + MTP_HEADER_DATA_SIZE
STATIC_BLOCK_HEADERS = False
SESSIONCLS = DashElectrumX
DAEMON = daemon.ZcoinMtpDaemon
DESERIALIZER = lib_tx.DeserializerZcoin
PEERS = [
'electrum.polispay.com',
]
@classmethod
def is_mtp(cls, header):
from electrumx.lib.util import unpack_le_uint32_from, hex_to_bytes
if isinstance(header, str):
nVersion, = unpack_le_uint32_from(hex_to_bytes(header[0:4*2]))
elif isinstance(header, bytes):
nVersion, = unpack_le_uint32_from(header[0:4])
else:
raise "Cannot handle the passed type"
return nVersion & 0x1000
@classmethod
def block_header(cls, block, height):
sz = cls.BASIC_HEADER_SIZE
if cls.is_mtp(block):
sz += cls.MTP_HEADER_EXTRA_SIZE
return block[:sz]
@classmethod
def header_hash_rev(cls, header):
sz = cls.BASIC_HEADER_SIZE
if cls.is_mtp(header):
sz += cls.MTP_HEADER_EXTRA_SIZE
return double_sha256(header[:sz])
class ZcoinTestnet(Zcoin):
SHORTNAME = "tXZC"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("41")
P2SH_VERBYTES = (bytes.fromhex("b2"),)
GENESIS_HASH = '1e3487fdb1a7d46dac3e8f3e58339c6e' \
'ff54abf6aef353485f3ed64250a35e89'
REORG_LIMIT = 8000
RPC_PORT = 18888
class Polis(Coin):
NAME = "Polis"
SHORTNAME = "POLIS"
NET = "mainnet"
GENESIS_HASH = ('000009701eb781a8113b1af1d814e2f0'
'60f6408a2c990db291bc5108a1345c1e')
P2PKH_VERBYTE = bytes.fromhex("37")
P2SH_VERBYTES = (bytes.fromhex("38"),)
TX_COUNT_HEIGHT = 280600
TX_COUNT = 635415
TX_PER_BLOCK = 4
RPC_PORT = 24127
PEERS = [
'electrum.polispay.com',
]
SESSIONCLS = DashElectrumX
DAEMON = daemon.DashDaemon
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
import dash_hash
return dash_hash.getPoWHash(header)
class MNPCoin(Coin):
NAME = "MNPCoin"
SHORTNAME = "MNP"
NET = "mainnet"
GENESIS_HASH = ('00000924036c67d803ce606ded814312'
'7e62fa2111dd3b063880a1067c69ccb1')
P2PKH_VERBYTE = bytes.fromhex("32")
P2SH_VERBYTES = (bytes.fromhex("35"),)
TX_COUNT_HEIGHT = 248000
TX_COUNT = 506447
TX_PER_BLOCK = 4
RPC_PORT = 13373
PEERS = [
'electrum.polispay.com',
]
SESSIONCLS = DashElectrumX
DAEMON = daemon.DashDaemon
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
import quark_hash
return quark_hash.getPoWHash(header)
class ColossusXT(Coin):
NAME = "ColossusXT"
SHORTNAME = "COLX"
NET = "mainnet"
GENESIS_HASH = ('a0ce8206c908357008c1b9a8ba2813af'
'f0989ca7f72d62b14e652c55f02b4f5c')
P2PKH_VERBYTE = bytes.fromhex("1E")
P2SH_VERBYTES = (bytes.fromhex("0D"),)
TX_COUNT_HEIGHT = 356500
BASIC_HEADER_SIZE = 80
HDR_V5_HEIGHT = 500000
HDR_V5_SIZE = 112
HDR_V5_START_OFFSET = HDR_V5_HEIGHT * BASIC_HEADER_SIZE
TX_COUNT = 761041
TX_PER_BLOCK = 4
RPC_PORT = 51473
PEERS = [
'electrum.polispay.com',
]
SESSIONCLS = DashElectrumX
DAEMON = daemon.DashDaemon
@classmethod
def static_header_offset(cls, height):
assert cls.STATIC_BLOCK_HEADERS
if height >= cls.HDR_V5_HEIGHT:
relative_v4_offset = (height - cls.HDR_V5_HEIGHT) * cls.HDR_V5_SIZE
return cls.HDR_V5_START_OFFSET + relative_v4_offset
else:
return height * cls.BASIC_HEADER_SIZE
@classmethod
def header_hash_rev(cls, header):
version, = util.unpack_le_uint32_from(header)
if version >= 5:
return super().header_hash_rev(header)
else:
import quark_hash
return quark_hash.getPoWHash(header)
class Minexcoin(EquihashMixin, Coin):
NAME = "Minexcoin"
SHORTNAME = "MNX"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("4b")
GENESIS_HASH = ('490a36d9451a55ed197e34aca7414b35'
'd775baa4a8e896f1c577f65ce2d214cb')
STATIC_BLOCK_HEADERS = True
BASIC_HEADER_SIZE = 209
HEADER_SIZE_NO_SOLUTION = 140
TX_COUNT = 327963
TX_COUNT_HEIGHT = 74495
TX_PER_BLOCK = 5
RPC_PORT = 8022
CHUNK_SIZE = 960
PEERS = [
'electrumx.xpresit.net s t',
'elex01-ams.turinex.eu s t',
'eu.minexpool.nl s t',
]
@classmethod
def block_header(cls, block, height):
'''Return the block header bytes'''
deserializer = cls.DESERIALIZER(block)
return deserializer.read_header(cls.HEADER_SIZE_NO_SOLUTION)
class Groestlcoin(Coin):
NAME = "Groestlcoin"
SHORTNAME = "GRS"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("24")
GENESIS_HASH = ('00000ac5927c594d49cc0bdb81759d0d'
'a8297eb614683d3acb62f0703b639023')
DESERIALIZER = lib_tx.DeserializerGroestlcoin
TX_COUNT = 115900
TX_COUNT_HEIGHT = 1601528
TX_PER_BLOCK = 5
RPC_PORT = 1441
BLACKLIST_URL = 'https://groestlcoin.org/blacklist.json'
PEERS = [
'electrum1.groestlcoin.org s t',
'electrum2.groestlcoin.org s t',
'glzyzqiulwclsowniyjeg5tspdojfgiiizbpnepcxoswqkmsjzlkucqd.onion t',
'jcv7kwu3gopzxp3r2ve43m6nahrxzc426hif4o3a2vt7wl4xq6tg3xqd.onion t',
]
def grshash(data):
import groestlcoin_hash
return groestlcoin_hash.getHash(data, len(data))
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
return cls.grshash(header)
ENCODE_CHECK = partial(Base58.encode_check, hash_fn=grshash)
DECODE_CHECK = partial(Base58.decode_check, hash_fn=grshash)
class GroestlcoinTestnet(Groestlcoin):
SHORTNAME = "TGRS"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("6f")
P2SH_VERBYTES = (bytes.fromhex("c4"),)
GENESIS_HASH = ('000000ffbb50fc9898cdd36ec163e6ba'
'23230164c0052a28876255b7dcf2cd36')
RPC_PORT = 17766
PEERS = [
'electrum-test1.groestlcoin.org s t',
'electrum-test2.groestlcoin.org s t',
'v2wuvscywpli35kgolqrt2kw67rqfbfwfn4bv3pc6gtugkexqv675uqd.onion t',
'75dycxl6lqxujplls3qkhkzffptzdfohv3y5um7s5nhyu6idayqmk7id.onion t',
]
class GroestlcoinRegtest(GroestlcoinTestnet):
SHORTNAME = "GRSRT"
NET = "regtest"
RPC_PORT = 18443
PEERS = []
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
class GroestlcoinSignet(GroestlcoinTestnet):
SHORTNAME = "SGRS"
NET = "signet"
GENESIS_HASH = ('0000007fcaa2a27993c6cde9e7818c25'
'4357af517b876ceba2f23592bb14ab31')
RPC_PORT = 31441
PEERS = []
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
class Pivx(Coin):
NAME = "PIVX"
SHORTNAME = "PIVX"
NET = "mainnet"
GENESIS_HASH = '0000041e482b9b9691d98eefb48473405c0b8ec31b76df3797c74a78680ef818'
P2PKH_VERBYTE = bytes.fromhex("1e")
P2SH_VERBYTE = bytes.fromhex("0d")
DESERIALIZER = lib_tx.DeserializerPIVX
TX_COUNT_HEIGHT = 569399
TX_COUNT = 2157510
TX_PER_BLOCK = 1
STATIC_BLOCK_HEADERS = False
RPC_PORT = 51470
REORG_LIMIT = 100
EXPANDED_HEADER = 112
ZEROCOIN_START_HEIGHT = 863787
ZEROCOIN_END_HEIGHT = 2153200
ZEROCOIN_BLOCK_VERSION = 4
SAPLING_START_HEIGHT = 2700500
@classmethod
def static_header_len(cls, height):
'''Given a header height return its length.'''
if (height >= cls.ZEROCOIN_START_HEIGHT and height < cls.ZEROCOIN_END_HEIGHT) \
or (height >= cls.SAPLING_START_HEIGHT):
return cls.EXPANDED_HEADER
else:
return cls.BASIC_HEADER_SIZE
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
version, = struct.unpack('<I', header[:4])
if version >= cls.ZEROCOIN_BLOCK_VERSION:
return super().header_hash_rev(header)
else:
import quark_hash
return quark_hash.getPoWHash(header)
class PivxTestnet(Pivx):
NET = "testnet"
GENESIS_HASH = '0000041e482b9b9691d98eefb48473405c0b8ec31b76df3797c74a78680ef818'
P2PKH_VERBYTE = bytes.fromhex("8B")
P2SH_VERBYTE = bytes.fromhex("13")
TX_PER_BLOCK = 4
RPC_PORT = 51472
ZEROCOIN_START_HEIGHT = 201
ZEROCOIN_END_HEIGHT = 201
ZEROCOIN_BLOCK_VERSION = 4
SAPLING_START_HEIGHT = 201
@classmethod
def static_header_len(cls, height):
'''Given a header height return its length.'''
if (height >= cls.ZEROCOIN_START_HEIGHT and height < cls.ZEROCOIN_END_HEIGHT) or (
height >= cls.SAPLING_START_HEIGHT):
return cls.EXPANDED_HEADER
else:
return cls.BASIC_HEADER_SIZE
class Bitg(Coin):
NAME = "BitcoinGreen"
SHORTNAME = "BITG"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("26")
P2SH_VERBYTES = (bytes.fromhex("06"),)
GENESIS_HASH = (
'000008467c3a9c587533dea06ad9380cded3ed32f9742a6c0c1aebc21bf2bc9b')
DAEMON = daemon.DashDaemon
TX_COUNT = 1000
TX_COUNT_HEIGHT = 10000
TX_PER_BLOCK = 1
RPC_PORT = 9332
REORG_LIMIT = 1000
SESSIONCLS = DashElectrumX
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
import quark_hash
return quark_hash.getPoWHash(header)
class tBitg(Bitg):
SHORTNAME = "tBITG"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("62")
P2SH_VERBYTES = (bytes.fromhex("0c"),)
GENESIS_HASH = (
'000008467c3a9c587533dea06ad9380cded3ed32f9742a6c0c1aebc21bf2bc9b')
RPC_PORT = 19332
class EXOS(Coin):
NAME = "EXOS"
SHORTNAME = "EXOS"
NET = "mainnet"
GENESIS_HASH = ('00000036090a68c523471da7a4f0f958'
'c1b4403fef74a003be7f71877699cab7')
P2PKH_VERBYTE = bytes.fromhex("1C")
P2SH_VERBYTE = [bytes.fromhex("57")]
RPC_PORT = 4561
TX_COUNT = 1000
TX_COUNT_HEIGHT = 10000
TX_PER_BLOCK = 4
DAEMON = daemon.PreLegacyRPCDaemon
DESERIALIZER = lib_tx.DeserializerTxTime
@classmethod
def header_hash_rev(cls, header):
version, = util.unpack_le_uint32_from(header)
if version > 2:
return double_sha256(header)
else:
return hex_str_to_hash(EXOS.GENESIS_HASH)
class EXOSTestnet(EXOS):
SHORTNAME = "tEXOS"
NET = "testnet"
GENESIS_HASH = ('0000059bb2c2048493efcb0f1a034972'
'b3ce4089d54c93b69aaab212fb369887')
P2PKH_VERBYTE = bytes.fromhex("4B")
P2SH_VERBYTE = [bytes.fromhex("CE")]
RPC_PORT = 14561
@classmethod
def header_hash_rev(cls, header):
version, = util.unpack_le_uint32_from(header)
if version > 2:
return double_sha256(header)
else:
return hex_str_to_hash(EXOSTestnet.GENESIS_HASH)
class SmartCash(Coin):
NAME = "SmartCash"
SHORTNAME = "SMART"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("3f")
P2SH_VERBYTES = (bytes.fromhex("12"),)
GENESIS_HASH = ('000007acc6970b812948d14ea5a0a13d'
'b0fdd07d5047c7e69101fa8b361e05a4')
DESERIALIZER = lib_tx.DeserializerSmartCash
RPC_PORT = 9679
REORG_LIMIT = 5000
TX_COUNT = 1115016
TX_COUNT_HEIGHT = 541656
TX_PER_BLOCK = 1
ENCODE_CHECK = partial(Base58.encode_check,
hash_fn=lib_tx.DeserializerSmartCash.keccak)
DECODE_CHECK = partial(Base58.decode_check,
hash_fn=lib_tx.DeserializerSmartCash.keccak)
HEADER_HASH = lib_tx.DeserializerSmartCash.keccak
DAEMON = daemon.SmartCashDaemon
SESSIONCLS = SmartCashElectrumX
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
return cls.HEADER_HASH(header)
class NIX(Coin):
NAME = "NIX"
SHORTNAME = "NIX"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("26")
P2SH_VERBYTES = (bytes.fromhex("35"),)
GENESIS_HASH = ('dd28ad86def767c3cfc34267a950d871'
'fc7462bc57ea4a929fc3596d9b598e41')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 114240
TX_COUNT_HEIGHT = 87846
TX_PER_BLOCK = 3
RPC_PORT = 6215
REORG_LIMIT = 1000
class NIXTestnet(NIX):
SHORTNAME = "tNIX"
NET = "testnet"
GENESIS_HASH = ('dd28ad86def767c3cfc34267a950d871'
'fc7462bc57ea4a929fc3596d9b598e41')
P2PKH_VERBYTE = bytes.fromhex("01")
P2SH_VERBYTE = [bytes.fromhex("03")]
RPC_PORT = 16215
DESERIALIZER = lib_tx.DeserializerSegWit
class Noir(Coin):
NAME = "Noir"
SHORTNAME = "NOR"
NET = "mainnet"
P2SH_VERBYTES = (bytes.fromhex("07"),)
GENESIS_HASH = ('23911212a525e3d149fcad6c559c8b17'
'f1e8326a272a75ff9bb315c8d96433ef')
RPC_PORT = 8825
TX_COUNT = 586369
TX_COUNT_HEIGHT = 379290
TX_PER_BLOCK = 5
class BitcoinPlus(Coin):
NAME = "BitcoinPlus"
SHORTNAME = "XBC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("19")
P2SH_VERBYTES = (bytes.fromhex("55"),)
GENESIS_HASH = ('0000005f6a28e686f641c616e56182d1'
'b43afbe08a223f23bda23cdf9d55b882')
DESERIALIZER = lib_tx.DeserializerTxTime
DAEMON = daemon.LegacyRPCDaemon
TX_COUNT = 1479247
TX_COUNT_HEIGHT = 749740
TX_PER_BLOCK = 2
RPC_PORT = 8885
REORG_LIMIT = 2000
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
import x13_hash
return x13_hash.getPoWHash(header)
class Myriadcoin(AuxPowMixin, Coin):
NAME = "Myriadcoin"
SHORTNAME = "XMY"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("32")
P2SH_VERBYTES = (bytes.fromhex("09"),)
GENESIS_HASH = ('00000ffde4c020b5938441a0ea3d314b'
'f619eff0b38f32f78f7583cffa1ea485')
DESERIALIZER = lib_tx.DeserializerAuxPowSegWit
TX_COUNT = 1976629
TX_COUNT_HEIGHT = 2580356
TX_PER_BLOCK = 20
REORG_LIMIT = 2000
RPC_PORT = 10889
class MyriadcoinTestnet(Myriadcoin):
NAME = "Myriadcoin"
SHORTNAME = "XMT"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("58")
P2SH_VERBYTES = (bytes.fromhex("bc"),)
GENESIS_HASH = ('0000017ce2a79c8bddafbbe47c004aa9'
'2b20678c354b34085f62b762084b9788')
# Source: https://github.com/LIMXTEC/BitSend
class Bitsend(Coin):
NAME = "Bitsend"
SHORTNAME = "BSD"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("66")
GENESIS_HASH = ('0000012e1b8843ac9ce8c18603658eaf'
'8895f99d3f5e7e1b7b1686f35e3c087a')
TX_COUNT = 974672
TX_COUNT_HEIGHT = 586022
TX_PER_BLOCK = 2
RPC_PORT = 8800
REORG_LIMIT = 1000
DESERIALIZER = lib_tx.DeserializerSegWit
XEVAN_TIMESTAMP = 1477958400
PEERS = [
'ele1.bitsend.cc s t',
'51.15.121.233 s t',
]
@classmethod
def header_hash_rev(cls, header):
timestamp, = util.unpack_le_uint32_from(header, 68)
if timestamp > cls.XEVAN_TIMESTAMP:
import xevan_hash
return xevan_hash.getPoWHash(header)
else:
import dash_hash
return dash_hash.getPoWHash(header)
@classmethod
def genesis_block(cls, block):
header = cls.block_header(block, 0)
header_hex_hash = hash_to_hex_str(cls.header_hash_rev(header))
if header_hex_hash != cls.GENESIS_HASH:
raise CoinError(f'genesis block has hash {header_hex_hash} '
f'expected {cls.GENESIS_HASH}')
return header + b'\0'
class Ravencoin(Coin):
NAME = "Ravencoin"
SHORTNAME = "RVN"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("3C")
P2SH_VERBYTES = (bytes.fromhex("7A"),)
GENESIS_HASH = ('0000006b444bc2f2ffe627be9d9e7e7a'
'0730000870ef6eb6da46c8eae389df90')
DESERIALIZER = lib_tx.DeserializerSegWit
X16RV2_ACTIVATION_TIME = 1569945600 # algo switch to x16rv2 at this timestamp
KAWPOW_ACTIVATION_TIME = 1588788000 # kawpow algo activation time
KAWPOW_ACTIVATION_HEIGHT = 1219736
KAWPOW_HEADER_SIZE = 120
TX_COUNT = 5626682
TX_COUNT_HEIGHT = 887000
TX_PER_BLOCK = 6
RPC_PORT = 8766
REORG_LIMIT = 100
PEERS = [
]
@classmethod
def static_header_offset(cls, height):
'''Given a header height return its offset in the headers file.'''
if cls.KAWPOW_ACTIVATION_HEIGHT < 0 or height <= cls.KAWPOW_ACTIVATION_HEIGHT:
result = height * cls.BASIC_HEADER_SIZE
else: # RVN block header size increased with kawpow fork
baseoffset = cls.KAWPOW_ACTIVATION_HEIGHT * cls.BASIC_HEADER_SIZE
result = baseoffset + ((height-cls.KAWPOW_ACTIVATION_HEIGHT) * cls.KAWPOW_HEADER_SIZE)
return result
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
timestamp = util.unpack_le_uint32_from(header, 68)[0]
assert cls.KAWPOW_ACTIVATION_TIME > 0
def reverse_bytes(data):
b = bytearray(data)
b.reverse()
return bytes(b)
if timestamp >= cls.KAWPOW_ACTIVATION_TIME:
import kawpow
nNonce64 = util.unpack_le_uint64_from(header, 80)[0] # uint64_t
mix_hash = reverse_bytes(header[88:120]) # uint256
header_hash = reverse_bytes(double_sha256(header[:80]))
final_hash = reverse_bytes(kawpow.light_verify(header_hash, mix_hash, nNonce64))
return final_hash
elif timestamp >= cls.X16RV2_ACTIVATION_TIME:
import x16rv2_hash
return x16rv2_hash.getPoWHash(header)
else:
import x16r_hash
return x16r_hash.getPoWHash(header)
class RavencoinTestnet(Ravencoin):
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("6F")
P2SH_VERBYTES = (bytes.fromhex("C4"),)
GENESIS_HASH = ('000000ecfc5e6324a079542221d00e10'
'362bdc894d56500c414060eea8a3ad5a')
X16RV2_ACTIVATION_TIME = 1567533600
KAWPOW_ACTIVATION_HEIGHT = 231544
KAWPOW_ACTIVATION_TIME = 1585159200
TX_COUNT = 496158
TX_COUNT_HEIGHT = 420500
TX_PER_BLOCK = 1
RPC_PORT = 18766
PEER_DEFAULT_PORTS = {'t': '50003', 's': '50004'}
REORG_LIMIT = 100
PEERS = [
]
class Bolivarcoin(Coin):
NAME = "Bolivarcoin"
SHORTNAME = "BOLI"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("55")
P2SH_VERBYTES = (bytes.fromhex("05"),)
GENESIS_HASH = ('00000e4fc293a1912b9d73cbb8d8f727'
'0007a7d84382f1370661e65d5d57b1f6')
TX_COUNT = 1082515
TX_COUNT_HEIGHT = 540410
TX_PER_BLOCK = 10
RPC_PORT = 3563
REORG_LIMIT = 800
PEERS = []
SESSIONCLS = DashElectrumX
DAEMON = daemon.DashDaemon
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
import dash_hash
return dash_hash.getPoWHash(header)
class Onixcoin(Coin):
NAME = "Onixcoin"
SHORTNAME = "ONX"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("4B")
GENESIS_HASH = ('000007140b7a6ca0b64965824f5731f6'
'e86daadf19eb299033530b1e61236e43')
TX_COUNT = 431808
TX_COUNT_HEIGHT = 321132
TX_PER_BLOCK = 10
RPC_PORT = 41019
REORG_LIMIT = 800
PEERS = []
SESSIONCLS = DashElectrumX
DAEMON = daemon.DashDaemon
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
import dash_hash
return dash_hash.getPoWHash(header)
class Electra(Coin):
NAME = "Electra"
SHORTNAME = "ECA"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("21")
P2SH_VERBYTES = (bytes.fromhex("28"),)
GENESIS_HASH = ('00000f98da995de0ef1665c7d3338687'
'923c1199230a44ecbdb5cec9306e4f4e')
RPC_PORT = 5788
TX_COUNT = 615729
TX_COUNT_HEIGHT = 205243
TX_PER_BLOCK = 3
REORG_LIMIT = 100
DESERIALIZER = lib_tx.DeserializerElectra
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
version, = util.unpack_le_uint32_from(header)
import nist5_hash
if version != 8:
return nist5_hash.getPoWHash(header)
else:
return double_sha256(header)
class ECCoin(Coin):
NAME = "ECCoin"
SHORTNAME = "ECC"
NET = "mainnet"
DESERIALIZER = lib_tx.DeserializerECCoin
P2PKH_VERBYTE = bytes.fromhex("21")
P2SH_VERBYTES = (bytes.fromhex("08"),)
GENESIS_HASH = 'a60ac43c88dbc44b826cf315352a8a7b373d2af8b6e1c4c4a0638859c5e9ecd1'
TX_COUNT = 4661197
TX_COUNT_HEIGHT = 2114846
TX_PER_BLOCK = 10
VALUE_PER_COIN = 1000000
RPC_PORT = 19119
@classmethod
def header_hash_rev(cls, header):
# Requires OpenSSL 1.1.0+
from hashlib import scrypt
return scrypt(header, salt=header, n=1024, r=1, p=1, dklen=32)
class Xaya(NameIndexAuxPoWMixin, Coin):
NAME = "Xaya"
SHORTNAME = "CHI"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1c")
P2SH_VERBYTES = (bytes.fromhex("1e"),)
GENESIS_HASH = ('e5062d76e5f50c42f493826ac9920b63'
'a8def2626fd70a5cec707ec47a4c4651')
TX_COUNT = 1147749
TX_COUNT_HEIGHT = 1030000
TX_PER_BLOCK = 2
DESERIALIZER = lib_tx.DeserializerXaya
TRUNCATED_HEADER_SIZE = 80 + 5
RPC_PORT = 8396
PEERS = [
'seeder.xaya.io s50002',
'xaya.domob.eu s50002',
]
# Op-codes for name operations
OP_NAME_REGISTER = OpCodes.OP_1
OP_NAME_UPDATE = OpCodes.OP_2
# Valid name prefixes.
NAME_REGISTER_OPS = [OP_NAME_REGISTER, "name", -1, OpCodes.OP_2DROP,
OpCodes.OP_DROP]
NAME_UPDATE_OPS = [OP_NAME_UPDATE, "name", -1, OpCodes.OP_2DROP,
OpCodes.OP_DROP]
NAME_OPERATIONS = (
NAME_REGISTER_OPS,
NAME_UPDATE_OPS,
)
@classmethod
def genesis_block(cls, block):
super().genesis_block(block)
# In Xaya, the genesis block's coinbase is spendable. Thus unlike
# the generic genesis_block() method, we return the full block here.
return block
class XayaTestnet(Xaya):
SHORTNAME = "XCH"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("58")
P2SH_VERBYTES = (bytes.fromhex("5a"),)
GENESIS_HASH = ('5195fc01d0e23d70d1f929f21ec55f47'
'e1c6ea1e66fae98ee44cbbc994509bba')
TX_COUNT = 51557
TX_COUNT_HEIGHT = 49000
TX_PER_BLOCK = 1
RPC_PORT = 18396
PEERS = []
class XayaRegtest(XayaTestnet):
NET = "regtest"
GENESIS_HASH = ('6f750b36d22f1dc3d0a6e483af453010'
'22646dfc3b3ba2187865f5a7d6d83ab1')
RPC_PORT = 18493
# Source: https://github.com/GZR0/GRZ0
class GravityZeroCoin(ScryptMixin, Coin):
NAME = "GravityZeroCoin"
SHORTNAME = "GZRO"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("26")
GENESIS_HASH = '0000028bfbf9ccaed8f28b3ca6b3ffe6b65e29490ab0e4430679bf41cc7c164f'
DAEMON = daemon.FakeEstimateLegacyRPCDaemon
TX_COUNT = 100
TX_COUNT_HEIGHT = 747635
TX_PER_BLOCK = 2
RPC_PORT = 36442
ESTIMATE_FEE = 0.01
RELAY_FEE = 0.01
class Simplicity(Coin):
NAME = "Simplicity"
SHORTNAME = "SPL"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("12")
P2SH_VERBYTE = bytes.fromhex("3b")
GENESIS_HASH = 'f4bbfc518aa3622dbeb8d2818a606b82c2b8b1ac2f28553ebdb6fc04d7abaccf'
RPC_PORT = 11958
TX_COUNT = 1726548
TX_COUNT_HEIGHT = 1040000
TX_PER_BLOCK = 5
REORG_LIMIT = 100
DESERIALIZER = lib_tx.DeserializerSimplicity
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
version, = util.unpack_le_uint32_from(header)
if version < 2:
import quark_hash
return quark_hash.getPoWHash(header)
else:
return double_sha256(header)
class ElectraProtocol(Coin):
NAME = 'ElectraProtocol'
SHORTNAME = 'XEP'
NET = 'mainnet'
P2PKH_VERBYTE = bytes.fromhex('37')
P2SH_VERBYTE = bytes.fromhex('89')
GENESIS_HASH = '000000954c02f260a6db02c712557adcb5a7a8a0a9acfd3d3c2b3a427376c56f'
RPC_PORT = 16816
TX_COUNT = 264299
TX_COUNT_HEIGHT = 130000
TX_PER_BLOCK = 5
REORG_LIMIT = 1080
DESERIALIZER = lib_tx.DeserializerSegWit
PEERS = [
'electrumx1.electraprotocol.eu s t',
'electrumx2.electraprotocol.eu s t',
'electrumx3.electraprotocol.eu s t',
'electrumx4.electraprotocol.eu s t',
'electrumx5.electraprotocol.eu s t',
]
@classmethod
def genesis_block(cls, block):
super().genesis_block(block)
# XEP has spendable genesis outputs, so we return the full block here.
return block
class Myce(Coin):
NAME = "Myce"
SHORTNAME = "YCE"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("32")
P2SH_VERBYTE = bytes.fromhex("55")
GENESIS_HASH = '0000c74cc66c72cb1a327c5c1d4893ae5276aa50be49fb23cec21df1a2f20d87'
RPC_PORT = 23512
TX_COUNT = 1568977
TX_COUNT_HEIGHT = 774450
TX_PER_BLOCK = 3
REORG_LIMIT = 100
DESERIALIZER = lib_tx.DeserializerSimplicity
@classmethod
def header_hash_rev(cls, header):
'''Given a header return the hash.'''
version, = util.unpack_le_uint32_from(header)
if version < 7:
# Requires OpenSSL 1.1.0+
from hashlib import scrypt
return scrypt(header, salt=header, n=1024, r=1, p=1, dklen=32)
else:
return double_sha256(header)
class Navcoin(Coin):
NAME = "Navcoin"
SHORTNAME = "NAV"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("35")
P2SH_VERBYTES = (bytes.fromhex("55"),)
GENESIS_HASH = ('00006a4e3e18c71c6d48ad6c261e2254'
'fa764cf29607a4357c99b712dfbb8e6a')
DESERIALIZER = lib_tx.DeserializerTxTimeSegWitNavCoin
TX_COUNT = 137641
TX_COUNT_HEIGHT = 3649662
TX_PER_BLOCK = 2
RPC_PORT = 44444
REORG_LIMIT = 1000
@classmethod
def header_hash_rev(cls, header):
if int.from_bytes(header[:4], "little") > 6:
return double_sha256(header)
else:
import x13_hash
return x13_hash.getPoWHash(header)
class Primecoin(PrimeChainPowMixin, Coin):
NAME = "Primecoin"
SHORTNAME = "XPM"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("17")
P2SH_VERBYTES = (bytes.fromhex("53"),)
GENESIS_HASH = ('963d17ba4dc753138078a2f56afb3af9'
'674e2546822badff26837db9a0152106')
DAEMON = daemon.FakeEstimateFeeDaemon
ESTIMATE_FEE = 1.
TX_COUNT = 7138730
TX_COUNT_HEIGHT = 3639500
TX_PER_BLOCK = 2
RPC_PORT = 9912
REORG_LIMIT = 5000
PEERS = [
'electrumx.primecoin.org s t',
]
class PrimecoinTestnet(Primecoin):
NAME = "PrimecoinTestnet"
SHORTNAME = "tXPM"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("6f")
P2SH_VERBYTES = (bytes.fromhex("c4"),)
GENESIS_HASH = ('221156cf301bc3585e72de34fe1efdb6'
'fbd703bc27cfc468faa1cdd889d0efa0')
RPC_PORT = 9914
PEERS = [
'electrumx.testnet.primecoin.org t',
]
class Unobtanium(AuxPowMixin, Coin):
NAME = "Unobtanium"
SHORTNAME = "UNO"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("82")
P2SH_VERBYTES = (bytes.fromhex("1e"),)
GENESIS_HASH = ('000004c2fc5fffb810dccc197d603690'
'099a68305232e552d96ccbe8e2c52b75')
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 1
RPC_PORT = 65535
REORG_LIMIT = 5000
class Linx(Coin):
NAME = "Linx"
SHORTNAME = "LINX"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("4b")
P2SH_VERBYTES = (bytes.fromhex("05"),)
GENESIS_HASH = ('3bafea350a70f75e7a1cd279999faed7'
'1a51852aae88fed3c38553cecc810a92')
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 1
RPC_PORT = 9381
REORG_LIMIT = 5000
class Flashcoin(Coin):
NAME = "Flashcoin"
SHORTNAME = "FLASH"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("44")
P2SH_VERBYTES = (bytes.fromhex("82"),)
GENESIS_HASH = ('aa0cf4f5ce0a3c550ce5674c1e808c41'
'7cf5077b4e95bda1d6fbaeaf4258972b')
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 1
RPC_PORT = 9385
REORG_LIMIT = 5000
class Defcoin(Coin):
NAME = "Defcoin"
SHORTNAME = "DEFC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1e")
P2SH_VERBYTES = bytes.fromhex("05")
GENESIS_HASH = ('192047379f33ffd2bbbab3d53b9c4b9e'
'9b72e48f888eadb3dcf57de95a6038ad')
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 1
RPC_PORT = 9386
REORG_LIMIT = 5000
DESERIALIZER = lib_tx.DeserializerAuxPowSegWit
class Auroracoin(Coin):
NAME = "Auroracoin"
SHORTNAME = "AUR"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("17")
P2SH_VERBYTES = bytes.fromhex("05")
GENESIS_HASH = ('2a8e100939494904af825b488596ddd5'
'36b3a96226ad02e0f7ab7ae472b27a8e')
TX_COUNT = 2800000
TX_COUNT_HEIGHT = 2778987
TX_PER_BLOCK = 1
RPC_PORT = 12341
REORG_LIMIT = 5000
class Smileycoin(Coin):
NAME = "Smileycoin"
SHORTNAME = "SMLY"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("19")
P2SH_VERBYTES = bytes.fromhex("05")
GENESIS_HASH = ('660f734cf6c6d16111bde201bbd21228'
'73f2f2c078b969779b9d4c99732354fd')
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 1
RPC_PORT = 9388
REORG_LIMIT = 5000
class Iop(Coin):
NAME = "Iop"
SHORTNAME = "IOP"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("75")
P2SH_VERBYTES = (bytes.fromhex("AE"),)
GENESIS_HASH = ('00000000bf5f2ee556cb9be8be64e077'
'6af14933438dbb1af72c41bfb6c82db3')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 1
RPC_PORT = 8337
REORG_LIMIT = 5000
class Egulden(Coin):
NAME = "Egulden"
SHORTNAME = "EFL"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("30")
P2SH_VERBYTES = (bytes.fromhex("05"),)
GENESIS_HASH = ('6d39f28ad01a7edd3e2374b355cf8c7f'
'8dbc1c5e4596ad3642fa6d10c2599217')
TX_COUNT = 13336629
TX_COUNT_HEIGHT = 1268206
TX_PER_BLOCK = 10
RPC_PORT = 9402
REORG_LIMIT = 5000
class Ixcoin(AuxPowMixin, Coin):
NAME = "ixcoin"
SHORTNAME = "IXC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("8a")
P2SH_VERBYTES = (bytes.fromhex("05"),)
GENESIS_HASH = ('0000000001534ef8893b025b9c1da672'
'50285e35c9f76cae36a4904fdf72c591')
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 1
RPC_PORT = 9406
REORG_LIMIT = 5000
class Batacoin(Coin):
NAME = "bata"
SHORTNAME = "BTA"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("19")
P2SH_VERBYTES = (bytes.fromhex("05"),)
GENESIS_HASH = ('b4bee36fd54a6176fd832f462641415c'
'142d50e4b378f71c041870c2b1186bc8')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 1
RPC_PORT = 9412
REORG_LIMIT = 5000
class Digitalcoin(Coin):
NAME = "digitalcoin"
SHORTNAME = "DGC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1e")
P2SH_VERBYTES = (bytes.fromhex("05"),)
GENESIS_HASH = ('5e039e1ca1dbf128973bf6cff98169e4'
'0a1b194c3b91463ab74956f413b2f9c8')
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 1
RPC_PORT = 9413
REORG_LIMIT = 5000
class Cannacoin(Coin):
NAME = "cannacoin"
SHORTNAME = "CCN"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1C")
P2SH_VERBYTES = (bytes.fromhex("05"),)
GENESIS_HASH = ('f1b4cdf03c86099a0758f1c018d1a10b'
'f05afab436c92b93b42bb88970de9821')
DESERIALIZER = lib_tx.DeserializerReddcoin
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 1
RPC_PORT = 1234
REORG_LIMIT = 5000
class Europecoin(Coin):
NAME = "europecoin"
SHORTNAME = "ERC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("21")
P2SH_VERBYTES = (bytes.fromhex("05"),)
GENESIS_HASH = ('000d0da26987ead011c5d568e627f7e3'
'd4a4f83a0b280b1134d8e7e366377f9a')
BASIC_HEADER_SIZE = 88
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 1
RPC_PORT = 9412
REORG_LIMIT = 5000
class Adcoin(Coin):
NAME = "Adcoin"
SHORTNAME = "ACC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1e")
P2SH_VERBYTES = (bytes.fromhex("0d"),)
GENESIS_HASH = ('000000fc5276647fd959f718c9526f87'
'f4858c4ef62f2e29d3772e4e37040a25')
BASIC_HEADER_SIZE = 112
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 1
RPC_PORT = 9416
REORG_LIMIT = 5000
class Lynx(Coin):
NAME = "Lynx"
SHORTNAME = "LYNX"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("2d")
P2SH_VERBYTES = (bytes.fromhex("16"),)
GENESIS_HASH = ('984b30fc9bb5e5ff424ad7f4ec193053'
'8a7b14a2d93e58ad7976c23154ea4a76')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 1
RPC_PORT = 9139
REORG_LIMIT = 5000
class LitecoinCash(Coin):
NAME = "LitecoinCash"
SHORTNAME = "LCC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1c")
P2SH_VERBYTES = (bytes.fromhex("32"), bytes.fromhex("05"))
GENESIS_HASH = ('12a765e31ffd4059bada1e25190f6e98'
'c99d9714d334efa41a195a7e7e04bfe2')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 1
RPC_PORT = 9140
REORG_LIMIT = 5000
class BitcoinPrivate(EquihashMixin, Coin):
NAME = "BitcoinPrivate"
SHORTNAME = "BTCP"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("1325")
P2SH_VERBYTES = (bytes.fromhex("13AF"),)
GENESIS_HASH = ('0007104ccda289427919efc39dc9e4d4'
'99804b7bebc22df55f8b834301260602')
DESERIALIZER = lib_tx.DeserializerZcash
TX_COUNT = 329196
TX_COUNT_HEIGHT = 68379
TX_PER_BLOCK = 5
RPC_PORT = 9335
REORG_LIMIT = 5000
class Aryacoin(Coin):
NAME = "aryacoin"
SHORTNAME = "AYA"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("17")
P2SH_VERBYTES = (bytes.fromhex("6f"),)
GENESIS_HASH = ('b553727635006d7faade229d152482df'
'b9da7822d41cf0cad9ffa82a54f67803')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 10
RPC_PORT = 9151
REORG_LIMIT = 800
class Donu(Coin):
NAME = "donu"
SHORTNAME = "DONU"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("35")
P2SH_VERBYTES = (bytes.fromhex("05"),)
GENESIS_HASH = ('5f7f26e24291f5be2351e1dcdab18bf9'
'4cee718940e6b9f2fbb46227434c3f12')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 10
RPC_PORT = 26381
REORG_LIMIT = 800
class Quebecoin(AuxPowMixin, Coin):
NAME = "Quebecoin"
SHORTNAME = "QBC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("3a")
P2SH_VERBYTES = (bytes.fromhex("05"),)
GENESIS_HASH = ('000008c2d57759af6462352ee9f4923d'
'97401cb599a9318e6595a2a74c26ea74')
DESERIALIZER = lib_tx.DeserializerAuxPowSegWit
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 20
REORG_LIMIT = 2000
RPC_PORT = 10890
class Beyondcoin(Coin):
NAME = "Beyondcoin"
SHORTNAME = "BYND"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("19")
P2SH_VERBYTES = [bytes.fromhex("1a"), bytes.fromhex("05")]
GENESIS_HASH = ('0a9e3b5fce3aee6e04f06dfd6ad380a6'
'c0f9d8420f53a4ca97845756ee5d56e7')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 287000
TX_COUNT_HEIGHT = 133700
TX_PER_BLOCK = 2
RPC_PORT = 10332
REORG_LIMIT = 5000
class Syscoin(AuxPowMixin, Coin):
NAME = "Syscoin"
SHORTNAME = "SYS"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("3f")
P2SH_VERBYTES = (bytes.fromhex("05"),)
GENESIS_HASH = ('0000022642db0346b6e01c2a397471f4'
'f12e65d4f4251ec96c1f85367a61a7ab')
DESERIALIZER = lib_tx.DeserializerAuxPowSegWit
TX_COUNT = 911232
TX_COUNT_HEIGHT = 954572
TX_PER_BLOCK = 1
RPC_PORT = 8370
REORG_LIMIT = 2000
CHUNK_SIZE = 360
class Lbry(Coin):
NAME = "Lbry"
SHORTNAME = "LBC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("55")
P2SH_VERBYTES = (bytes.fromhex("7a"),)
GENESIS_HASH = ('9c89283ba0f3227f6c03b70216b9f665'
'f0118d5e0fa729cedf4fb34d6a34f463')
DESERIALIZER = lib_tx.DeserializerSegWit
BASIC_HEADER_SIZE = 112
TX_COUNT = 50792939
TX_COUNT_HEIGHT = 1178612
TX_PER_BLOCK = 43
RPC_PORT = 9245
REORG_LIMIT = 5000
class Garlicoin(Coin):
NAME = "Garlicoin"
SHORTNAME = "GRLC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("26")
P2SH_VERBYTES = [bytes.fromhex("32"), bytes.fromhex("05")]
GENESIS_HASH = ('2ada80bf415a89358d697569c96eb98c'
'dbf4c3b8878ac5722c01284492e27228')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 1031869
TX_COUNT_HEIGHT = 2343659
TX_PER_BLOCK = 2
RPC_PORT = 42068
REORG_LIMIT = 800
PEERS = [
'us.node.garlico.in s',
'ca.node.garlico.in s t',
'sg.node.garlico.in s',
'de.node.garlico.in s',
'fr.garlium.crapules.org s',
'uk.garlium.crapules.org s',
'pl.garlium.crapules.org s',
'ca.garlium.crapules.org s',
'au.garlium.crapules.org s',
'electrum.hotgrlc.com s t',
'electrum.maxpuig.com s t',
]
class Ferrite(Coin):
NAME = "Ferrite"
SHORTNAME = "FEC"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("24")
P2SH_VERBYTES = (bytes.fromhex("23"), bytes.fromhex("05"))
GENESIS_HASH = ('46ca17415c18e43f5292034ebf9bbd10'
'de80a61fc6dc17180e6609f33d3b48f3')
DESERIALIZER = lib_tx.DeserializerSegWit
TX_COUNT = 164010
TX_COUNT_HEIGHT = 150251
TX_PER_BLOCK = 2
RPC_PORT = 9573
REORG_LIMIT = 800
ESTIMATE_FEE = 0.00001
RELAY_FEE = 0.00001
PEERS = [
'enode1.ferritecoin.org s t',
'enode2.ferritecoin.org s t',
'enode3.ferritecoin.org s t',
]
class FerriteTestnet(Ferrite):
SHORTNAME = "TFE"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("6f")
P2SH_VERBYTES = (bytes.fromhex("23"), bytes.fromhex("c4"))
GENESIS_HASH = ('7a9f43d6e86eefa66e2b79918b2235c9'
'362106f3d9f11f37f7a33450ceae73c1')
TX_COUNT = 12445
TX_COUNT_HEIGHT = 6290
TX_PER_BLOCK = 2
RPC_PORT = 19573
REORG_LIMIT = 4000
ESTIMATE_FEE = 0.00001
RELAY_FEE = 0.00001
PEERS = [
'enode1.ferritecoin.org s t',
'enode2.ferritecoin.org s t',
'enode3.ferritecoin.org s t',
]
2026-10-22 14:54:54 +02:00
class Palladium(Bitcoin):
"""Palladium (PLM), a Bitcoin Core 0.19-based chain. Standard 80-byte headers, sha256d PoW, segwit.
Its daemon predates 'txospenderindex', 'getindexinfo' and 'submitpackage', so
'blockchain.outpoint.subscribe' and 'blockchain.transaction.broadcast_package' will
return daemon errors to clients. The daemon needs 'txindex=1'.
"""
NAME = "Palladium"
SHORTNAME = "PLM"
NET = "mainnet"
P2PKH_VERBYTE = bytes.fromhex("37")
P2SH_VERBYTES = (bytes.fromhex("05"),)
# same genesis block as Bitcoin mainnet
GENESIS_HASH = ('000000000019d6689c085ae165831e93'
'4ff763ae46a2a6c172b3f1b60a8ce26f')
CRASH_CLIENT_VER = None
MIN_REQUIRED_DAEMON_VERSION = None
REQUIRED_DAEMON_INDEXES = tuple()
RPC_PORT = 2332
# snapshot (UpdateTip tx= count), only used for sync ETAs
TX_COUNT = 661_421
TX_COUNT_HEIGHT = 542_032
TX_PER_BLOCK = 2
PEERS = []
@classmethod
def warn_old_client_on_tx_broadcast(cls, client_ver):
return False
class PalladiumTestnet(Palladium):
SHORTNAME = "TPLM"
NET = "testnet"
P2PKH_VERBYTE = bytes.fromhex("7f")
P2SH_VERBYTES = (bytes.fromhex("73"),)
# same genesis block as Bitcoin testnet3
GENESIS_HASH = ('000000000933ea01ad0ee984209779ba'
'aec3ced90fa3f408719526f8d77f4943')
RPC_PORT = 12332
REORG_LIMIT = 8000
TX_COUNT = 1
TX_COUNT_HEIGHT = 1
TX_PER_BLOCK = 2
PEER_DEFAULT_PORTS = {'t': '51001', 's': '51002'}
class PalladiumRegtest(PalladiumTestnet):
NET = "regtest"
# same genesis block as Bitcoin regtest
GENESIS_HASH = ('0f9188f13cb7b2c71f2a335e3a4fc328'
'bf5beb436012afca590b1a11466e2206')
RPC_PORT = 28443