class AbosomMainnet(AbstractNet, StakeMixin): NAME = 'Abosom' NAME_LOWER = 'abosom' SHORT_CODE = 'ABOSOM' DATA_DIR = 'abosom' OPEN_ALIAS_PREFIX = 'abosom' PAYMENT_URI_SCHEME = 'abosom' PAYMENT_REQUEST_PKI_TYPE = "dnssec+abosom" APPLICATION_PAYMENT_REQUEST_TYPE = 'application/abosom-paymentrequest' APPLICATION_PAYMENT_TYPE = 'application/abosom-payment' APPLICATION_PAYMENT_ACK_TYPE = 'application/abosom-paymentack' BASE_UNITS = {'ABOSOM': 8, 'mABOSOM': 5, 'uABOSOM': 2, 'satoshi': 0} BASE_UNITS_INVERSE = inv_dict(BASE_UNITS) BASE_UNITS_LIST = ['ABOSOM', 'mABOSOM', 'uABOSOM', 'satoshi'] TESTNET = False WIF_PREFIX = 0x80 ADDRTYPE_P2PKH = 75 ADDRTYPE_P2SH = 78 XPRV_HEADERS = { 'standard': 0x800001c8, } XPRV_HEADERS_INV = inv_dict(XPRV_HEADERS) XPUB_HEADERS = { 'standard': 0x800001c8, } XPUB_HEADERS_INV = inv_dict(XPUB_HEADERS) BIP44_COIN_TYPE = 704 GENESIS = "00000e8048ffa0a80549ed405640e95e01590e70baf4888ef594d87402635697" DEFAULT_PORTS = {'t': '50041', 's': '50042'} DEFAULT_SERVERS = read_json('servers/Abosom-Mainnet.json', {}) CHECKPOINTS = read_json('checkpoints/Abosom-Mainnet.json', []) LN_REALM_BYTE = 0 LN_DNS_SEEDS = [] COINBASE_MATURITY = 8 COIN = 1000000 TOTAL_COIN_SUPPLY_LIMIT = 110000000 SIGNED_MESSAGE_PREFIX = b"\x18Abosom Signed Message:\n"
class BitcoinMainnet(AbstractNet): NAME = 'Bitcoin' NAME_LOWER = 'bitcoin' SHORT_CODE = 'BTC' TESTNET = False WIF_PREFIX = 0x80 ADDRTYPE_P2PKH = 0 ADDRTYPE_P2SH = 5 SEGWIT_HRP = "bc" GENESIS = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f" DEFAULT_PORTS = {'t': '50001', 's': '50002'} DEFAULT_SERVERS = read_json('servers/Bitcoin-Mainnet.json', {}) CHECKPOINTS = read_json('checkpoints/Bitcoin-Mainnet.json', []) BLOCK_HEIGHT_FIRST_LIGHTNING_CHANNELS = 497000 DATA_DIR = None DEV_FEE_ADDRESS = "3DY72R2mJUnFYUdgrAXLCWjy4gKyWHeuU4" XPRV_HEADERS = { 'standard': 0x0488ade4, # xprv 'p2wpkh-p2sh': 0x049d7878, # yprv 'p2wsh-p2sh': 0x0295b005, # Yprv 'p2wpkh': 0x04b2430c, # zprv 'p2wsh': 0x02aa7a99, # Zprv } XPRV_HEADERS_INV = inv_dict(XPRV_HEADERS) XPUB_HEADERS = { 'standard': 0x0488b21e, # xpub 'p2wpkh-p2sh': 0x049d7cb2, # ypub 'p2wsh-p2sh': 0x0295b43f, # Ypub 'p2wpkh': 0x04b24746, # zpub 'p2wsh': 0x02aa7ed3, # Zpub } XPUB_HEADERS_INV = inv_dict(XPUB_HEADERS) BIP44_COIN_TYPE = 0 LN_REALM_BYTE = 0 LN_DNS_SEEDS = [ 'nodes.lightning.directory.', 'lseed.bitcoinstats.com.', ] APPLICATION_PAYMENT_REQUEST_TYPE = 'application/bitcoin-paymentrequest' APPLICATION_PAYMENT_TYPE = 'application/bitcoin-payment' APPLICATION_PAYMENT_ACK_TYPE = 'application/bitcoin-paymentack' OPEN_ALIAS_PREFIX = 'btc' PAYMENT_URI_SCHEME = 'bitcoin' PAYMENT_REQUEST_PKI_TYPE = "dnssec+btc" COINBASE_MATURITY = 100 COIN = 100000000 TOTAL_COIN_SUPPLY_LIMIT = 21000000 SIGNED_MESSAGE_PREFIX = b"\x18Bitcoin Signed Message:\n" BASE_UNITS = {'BTC': 8, 'mBTC': 5, 'bits': 2, 'sat': 0} BASE_UNITS_INVERSE = inv_dict(BASE_UNITS) BASE_UNITS_LIST = ['BTC', 'mBTC', 'bits', 'sat'] DECIMAL_POINT_DEFAULT = 5 # mBTC BLOCK_EXPLORERS = { 'Bitupper Explorer': ('https://bitupper.com/en/explorer/bitcoin/', { 'tx': 'transactions/', 'addr': 'addresses/' }), 'Bitflyer.jp': ('https://chainflyer.bitflyer.jp/', { 'tx': 'Transaction/', 'addr': 'Address/' }), 'Blockchain.info': ('https://blockchain.com/btc/', { 'tx': 'tx/', 'addr': 'address/' }), 'blockchainbdgpzk.onion': ('https://blockchainbdgpzk.onion/', { 'tx': 'tx/', 'addr': 'address/' }), 'Blockstream.info': ('https://blockstream.info/', { 'tx': 'tx/', 'addr': 'address/' }), 'Bitaps.com': ('https://btc.bitaps.com/', { 'tx': '', 'addr': '' }), 'BTC.com': ('https://btc.com/', { 'tx': '', 'addr': '' }), 'Chain.so': ('https://www.chain.so/', { 'tx': 'tx/BTC/', 'addr': 'address/BTC/' }), 'Insight.is': ('https://insight.bitpay.com/', { 'tx': 'tx/', 'addr': 'address/' }), 'TradeBlock.com': ('https://tradeblock.com/blockchain/', { 'tx': 'tx/', 'addr': 'address/' }), 'BlockCypher.com': ('https://live.blockcypher.com/btc/', { 'tx': 'tx/', 'addr': 'address/' }), 'Blockchair.com': ('https://blockchair.com/bitcoin/', { 'tx': 'transaction/', 'addr': 'address/' }), 'blockonomics.co': ('https://www.blockonomics.co/', { 'tx': 'api/tx?txid=', 'addr': '#/search?q=' }), 'OXT.me': ('https://oxt.me/', { 'tx': 'transaction/', 'addr': 'address/' }), 'smartbit.com.au': ('https://www.smartbit.com.au/', { 'tx': 'tx/', 'addr': 'address/' }), 'mynode.local': ('http://mynode.local:3002/', { 'tx': 'tx/', 'addr': 'address/' }), 'system default': ('blockchain:/', { 'tx': 'tx/', 'addr': 'address/' }), } TARGET_TIMESPAN = int(14 * 24 * 60 * 60) TARGET_SPACING = int(10 * 60) INTERVAL = int(TARGET_TIMESPAN / TARGET_SPACING) @classmethod def get_target(cls, height: int, blockchain) -> int: index = height // 2016 - 1 if index == -1: return cls.MAX_TARGET if index < len(blockchain.checkpoints): h, t = blockchain.checkpoints[index] return t if not height % cls.INTERVAL == 0: # Get the first block of this retarget period last = blockchain.read_header(height - 1) if not last: raise MissingHeader() return blockchain.bits_to_target(last['bits']) # new target first = blockchain.read_header(height - cls.INTERVAL) last = blockchain.read_header(height - 1) if not first or not last: raise MissingHeader() bits = last.get('bits') target = blockchain.bits_to_target(bits) nActualTimespan = last.get('timestamp') - first.get('timestamp') nActualTimespan = max(nActualTimespan, cls.TARGET_TIMESPAN // 4) nActualTimespan = min(nActualTimespan, cls.TARGET_TIMESPAN * 4) new_target = min(cls.MAX_TARGET, (target * nActualTimespan) // cls.TARGET_TIMESPAN) # not any target can be represented in 32 bits: new_target = blockchain.bits_to_target( blockchain.target_to_bits(new_target)) return new_target
class ScalarisMainnet(AbstractNet, StakeMixin): NAME = 'Scalaris' NAME_LOWER = 'scalaris' SHORT_CODE = 'SCA' DATA_DIR = 'scalaris' OPEN_ALIAS_PREFIX = 'sca' PAYMENT_URI_SCHEME = 'scalaris' PAYMENT_REQUEST_PKI_TYPE = "dnssec+sca" APPLICATION_PAYMENT_REQUEST_TYPE = 'application/scalaris-paymentrequest' APPLICATION_PAYMENT_TYPE = 'application/scalaris-payment' APPLICATION_PAYMENT_ACK_TYPE = 'application/scalaris-paymentack' BASE_UNITS = {'SCA': 8, 'mSCA': 5, 'uSCA': 2, 'swartz': 0} BASE_UNITS_INVERSE = inv_dict(BASE_UNITS) BASE_UNITS_LIST = ['SCA', 'mSCA', 'uSCA', 'swartz'] TESTNET = False WIF_PREFIX = 0x9a ADDRTYPE_P2PKH = 63 ADDRTYPE_P2SH = 23 XPRV_HEADERS = { 'standard': 0x0488ade4, } XPRV_HEADERS_INV = inv_dict(XPRV_HEADERS) XPUB_HEADERS = { 'standard': 0x0488b21e, } XPUB_HEADERS_INV = inv_dict(XPUB_HEADERS) BIP44_COIN_TYPE = 921 GENESIS = "000003bf95cf7875987b333cc8e49a7c1a83583e5f5039b9af9555a92cb29651" DEFAULT_PORTS = {'t': '10001', 's': '10002'} DEFAULT_SERVERS = read_json('servers/Scalaris-Mainnet.json', {}) CHECKPOINTS = read_json('checkpoints/Scalaris-Mainnet.json', []) LN_REALM_BYTE = 0 LN_DNS_SEEDS = [] COINBASE_MATURITY = 100 COIN = 100000000 TOTAL_COIN_SUPPLY_LIMIT = 999999999999 SIGNED_MESSAGE_PREFIX = b"\x18Scalaris Signed Message:\n" DECIMAL_POINT_DEFAULT = 8 # SCA TARGET_SPACING = int(2 * 60) DGW_FORK_BLOCK = 0 BLOCK_EXPLORERS = { 'explorer.scalaris.info': ('https://explorer.scalaris.info', { 'tx': '/tx/', 'addr': '/address/' }), 'openchains.info': ('https://openchains.info', { 'tx': '/coin/scalaris/tx/', 'addr': '/coin/scalaris/address/' }), } @classmethod def hash_raw_header(cls, header): import algomodule return hash_encode(algomodule._quark_hash(bfh(header))) @classmethod def get_target(cls, height: int, blockchain) -> int: index = height // 2016 - 1 if index == -1: return cls.MAX_TARGET # Blockchain is PURE POS so we dont have the info needed to # calculate the targets required return 0
class DonuMainnet(AbstractNet, StakeMixin): NAME = 'Donu' NAME_LOWER = 'donu' SHORT_CODE = 'DONU' DATA_DIR = 'donu' OPEN_ALIAS_PREFIX = 'donu' PAYMENT_URI_SCHEME = 'donu' PAYMENT_REQUEST_PKI_TYPE = "dnssec+donu" APPLICATION_PAYMENT_REQUEST_TYPE = 'application/donu-paymentrequest' APPLICATION_PAYMENT_TYPE = 'application/donu-payment' APPLICATION_PAYMENT_ACK_TYPE = 'application/donu-paymentack' BASE_UNITS = {'DONU': 8, 'mDONU': 5, 'uDONU': 2, 'satoshi': 0} BASE_UNITS_INVERSE = inv_dict(BASE_UNITS) BASE_UNITS_LIST = ['DONU', 'mDONU', 'uDONU', 'satoshi'] TESTNET = False WIF_PREFIX = 0x80 ADDRTYPE_P2PKH = 53 ADDRTYPE_P2SH = 5 XPRV_HEADERS = { 'standard': 0x0488ade4, } XPRV_HEADERS_INV = inv_dict(XPRV_HEADERS) XPUB_HEADERS = { 'standard': 0x0488b21e, } XPUB_HEADERS_INV = inv_dict(XPUB_HEADERS) BIP44_COIN_TYPE = 405 SEGWIT_HRP = "dn" GENESIS = "000000008507af1fdaaf3fed6173005b23b0febf72e7c2094f11f1d057692182" DEFAULT_PORTS = {'t': '50001', 's': '50002'} DEFAULT_SERVERS = read_json('servers/Donu-Mainnet.json', {}) CHECKPOINTS = read_json('checkpoints/Donu-Mainnet.json', []) LN_REALM_BYTE = 0 LN_DNS_SEEDS = [] COINBASE_MATURITY = 100 COIN = 1000000 TOTAL_COIN_SUPPLY_LIMIT = 21000000 SIGNED_MESSAGE_PREFIX = b"\x18Donu Signed Message:\n" DECIMAL_POINT_DEFAULT = 8 # DONU TARGET_SPACING = int(2 * 60) POS_START_HEIGHT = 0 BLOCK_EXPLORERS = { 'CryptoID.info': ('https://chainz.cryptoid.info/donu/', { 'tx': 'tx.dws?', 'addr': 'address.dws?' }), 'system default': ('blockchain:/', { 'tx': 'tx/', 'addr': 'address/' }), } @classmethod def get_target(cls, height: int, blockchain) -> int: index = height // 2016 - 1 if index == -1: return cls.MAX_TARGET # Blockchain is PURE POS so we dont have the info needed to # calculate the targets required return 0
class NamecoinMainnet(AbstractNet, AuxPowMixin): NAME = 'Namecoin' NAME_LOWER = 'namecoin' SHORT_CODE = 'NMC' TESTNET = False WIF_PREFIX = 180 ADDRTYPE_P2PKH = 52 ADDRTYPE_P2SH = 13 SEGWIT_HRP = "nc" GENESIS = "000000000062b72c5e2ceb45fbc8587e807c155b0da735e6483dfba2f0a9c770" DEFAULT_PORTS = {'t': '50001', 's': '50002'} DEFAULT_SERVERS = read_json('servers/Namecoin-Mainnet.json', {}) CHECKPOINTS = read_json('checkpoints/Namecoin-Mainnet.json', []) BLOCK_HEIGHT_FIRST_LIGHTNING_CHANNELS = 497000 DATA_DIR = 'namecoin' XPRV_HEADERS = { 'standard': 0x0488ade4, # xprv 'p2wpkh-p2sh': 0x049d7878, # yprv 'p2wsh-p2sh': 0x0295b005, # Yprv 'p2wpkh': 0x04b2430c, # zprv 'p2wsh': 0x02aa7a99, # Zprv } XPRV_HEADERS_INV = inv_dict(XPRV_HEADERS) XPUB_HEADERS = { 'standard': 0x0488b21e, # xpub 'p2wpkh-p2sh': 0x049d7cb2, # ypub 'p2wsh-p2sh': 0x0295b43f, # Ypub 'p2wpkh': 0x04b24746, # zpub 'p2wsh': 0x02aa7ed3, # Zpub } XPUB_HEADERS_INV = inv_dict(XPUB_HEADERS) BIP44_COIN_TYPE = 7 LN_REALM_BYTE = 0 LN_DNS_SEEDS = [] OPEN_ALIAS_PREFIX = 'nmc' PAYMENT_URI_SCHEME = 'namecoin' PAYMENT_REQUEST_PKI_TYPE = "dnssec+nmc" APPLICATION_PAYMENT_REQUEST_TYPE = 'application/namecoin-paymentrequest' APPLICATION_PAYMENT_TYPE = 'application/namecoin-payment' APPLICATION_PAYMENT_ACK_TYPE = 'application/namecoin-paymentack' COINBASE_MATURITY = 100 COIN = 100000000 TOTAL_COIN_SUPPLY_LIMIT = 21000000 SIGNED_MESSAGE_PREFIX = b"\x18Namecoin Signed Message:\n" BASE_UNITS = {'NMC': 8, 'mNMC': 5, 'uNMC': 2, 'swartz': 0} BASE_UNITS_INVERSE = inv_dict(BASE_UNITS) BASE_UNITS_LIST = ['NMC', 'mNMC', 'uNMC', 'swartz'] DECIMAL_POINT_DEFAULT = 5 # mNMC AUXPOW_CHAIN_ID = 0x0001 AUXPOW_START_HEIGHT = 19200 BLOCK_VERSION_AUXPOW_BIT = 0x100 BLOCK_EXPLORERS = { 'Cyphrs.com': ('https://namecoin.cyphrs.com/', { 'tx': 'tx/', 'addr': 'address/' }), 'Namecha.in (non-libre; wiretapped by Cloudflare; discriminates against Tor)': ('https://namecha.in/', { 'tx': 'tx/', 'addr': 'address/' }), 'Bchain.info (non-libre; no name support)': ('https://bchain.info/NMC/', { 'tx': 'tx/', 'addr': 'addr/' }), 'BitInfoCharts.com (non-libre; wiretapped by Cloudflare; discriminates against Tor; no name support)': ('https://bitinfocharts.com/namecoin/', { 'tx': 'tx/', 'addr': 'address/' }), 'mynode.local': ('http://mynode.local:3002/', { 'tx': 'tx/', 'addr': 'address/' }), 'system default': ('blockchain:/', { 'tx': 'tx/', 'addr': 'address/' }), } # The default Bitcoin frame size limit of 1 MB doesn't work for AuxPoW-based # chains, because those chains' block headers have extra AuxPoW data. A limit # of 10 MB works fine for Namecoin as of block height 418744 (5 MB fails after # height 155232); we set a limit of 20 MB so that we have extra wiggle room. MAX_INCOMING_MSG_SIZE = 20_000_000 # in bytes TARGET_TIMESPAN = int(14 * 24 * 60 * 60) TARGET_SPACING = int(10 * 60) INTERVAL = int(TARGET_TIMESPAN / TARGET_SPACING) @classmethod def get_target(cls, height: int, blockchain) -> int: index = height // 2016 - 1 if index == -1: return cls.MAX_TARGET if index < len(blockchain.checkpoints): h, t = blockchain.checkpoints[index] return t if not height % cls.INTERVAL == 0: # Get the first block of this retarget period last = blockchain.read_header(height - 1) if not last: raise MissingHeader() return blockchain.bits_to_target(last['bits']) # new target if (index * 2016 + 2015 > 19200) and (index * 2016 + 2015 + 1 > 2016): # Namecoin: Apply retargeting hardfork after AuxPoW start first = blockchain.read_header(height - cls.INTERVAL - 1) else: first = blockchain.read_header(height - cls.INTERVAL) last = blockchain.read_header(height - 1) if not first or not last: raise MissingHeader() bits = last.get('bits') target = blockchain.bits_to_target(bits) nActualTimespan = last.get('timestamp') - first.get('timestamp') nActualTimespan = max(nActualTimespan, cls.TARGET_TIMESPAN // 4) nActualTimespan = min(nActualTimespan, cls.TARGET_TIMESPAN * 4) new_target = min(cls.MAX_TARGET, (target * nActualTimespan) // cls.TARGET_TIMESPAN) # not any target can be represented in 32 bits: new_target = blockchain.bits_to_target( blockchain.target_to_bits(new_target)) return new_target
class AbosomMainnet(AbstractNet, StakeMixin): NAME = 'Abosom' NAME_LOWER = 'abosom' SHORT_CODE = 'ABOSOM' DATA_DIR = 'abosom' OPEN_ALIAS_PREFIX = 'abosom' PAYMENT_URI_SCHEME = 'abosom' PAYMENT_REQUEST_PKI_TYPE = "dnssec+abosom" APPLICATION_PAYMENT_REQUEST_TYPE = 'application/abosom-paymentrequest' APPLICATION_PAYMENT_TYPE = 'application/abosom-payment' APPLICATION_PAYMENT_ACK_TYPE = 'application/abosom-paymentack' BASE_UNITS = {'ABOSOM': 8, 'mABOSOM': 5, 'uABOSOM': 2, 'satoshi': 0} BASE_UNITS_INVERSE = inv_dict(BASE_UNITS) BASE_UNITS_LIST = ['ABOSOM', 'mABOSOM', 'uABOSOM', 'satoshi'] TESTNET = False WIF_PREFIX = 0x80 ADDRTYPE_P2PKH = 75 ADDRTYPE_P2SH = 78 XPRV_HEADERS = { 'standard': 0x800001c8, } XPRV_HEADERS_INV = inv_dict(XPRV_HEADERS) XPUB_HEADERS = { 'standard': 0x800101c8, } XPUB_HEADERS_INV = inv_dict(XPUB_HEADERS) BIP44_COIN_TYPE = 704 GENESIS = "00000e8048ffa0a80549ed405640e95e01590e70baf4888ef594d87402635697" DEFAULT_PORTS = {'t': '50041', 's': '50042'} DEFAULT_SERVERS = read_json('servers/Abosom-Mainnet.json', {}) CHECKPOINTS = read_json('checkpoints/Abosom-Mainnet.json', []) LN_REALM_BYTE = 0 LN_DNS_SEEDS = [] COINBASE_MATURITY = 8 COIN = 1000000 TOTAL_COIN_SUPPLY_LIMIT = 110000000 SIGNED_MESSAGE_PREFIX = b"\x18Abosom Signed Message:\n" DECIMAL_POINT_DEFAULT = 8 # CRW TARGET_TIMESPAN = int(24 * 60 * 60) TARGET_SPACING = int(60) INTERVAL = int(TARGET_TIMESPAN / TARGET_SPACING) POS_START_HEIGHT = 1 BLOCK_EXPLORERS = { 'system default': ('blockchain:/', { 'tx': 'tx/', 'addr': 'address/' }), } @classmethod def hash_raw_header(cls, header): import algomodule return hash_encode(algomodule._x11_hash(bfh(header))) @classmethod def is_pos_active(cls, header) -> bool: return True @classmethod def get_target(cls, height: int, blockchain) -> int: index = height // 2016 - 1 if index == -1: return cls.MAX_TARGET if index < len(blockchain.checkpoints): h, t = blockchain.checkpoints[index] return t return cls.get_target_btc(height, blockchain) @classmethod def get_target_btc(cls, height: int, blockchain) -> int: if not height % cls.INTERVAL == 0: # Get the first block of this retarget period last = blockchain.read_header(height - 1) if not last: raise MissingHeader() return blockchain.bits_to_target(last['bits']) # new target first = blockchain.read_header(height - cls.INTERVAL) last = blockchain.read_header(height - 1) if not first or not last: raise MissingHeader() bits = last.get('bits') target = blockchain.bits_to_target(bits) nActualTimespan = last.get('timestamp') - first.get('timestamp') nActualTimespan = max(nActualTimespan, cls.TARGET_TIMESPAN // 4) nActualTimespan = min(nActualTimespan, cls.TARGET_TIMESPAN * 4) new_target = min(cls.MAX_TARGET, (target * nActualTimespan) // cls.TARGET_TIMESPAN) # not any target can be represented in 32 bits: new_target = blockchain.bits_to_target( blockchain.target_to_bits(new_target)) return new_target
class BitcoinTestnet(BitcoinMainnet): NAME = 'Bitcoin Testnet' NAME_LOWER = 'testnet bitcoin' TESTNET = True WIF_PREFIX = 0xef ADDRTYPE_P2PKH = 111 ADDRTYPE_P2SH = 196 SEGWIT_HRP = "tb" GENESIS = "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943" DEFAULT_PORTS = {'t': '51001', 's': '51002'} DEFAULT_SERVERS = read_json('servers/Bitcoin-Testnet.json', {}) CHECKPOINTS = read_json('checkpoints/Bitcoin-Testnet.json', []) DATA_DIR = 'testnet' XPRV_HEADERS = { 'standard': 0x04358394, # tprv 'p2wpkh-p2sh': 0x044a4e28, # uprv 'p2wsh-p2sh': 0x024285b5, # Uprv 'p2wpkh': 0x045f18bc, # vprv 'p2wsh': 0x02575048, # Vprv } XPRV_HEADERS_INV = inv_dict(XPRV_HEADERS) XPUB_HEADERS = { 'standard': 0x043587cf, # tpub 'p2wpkh-p2sh': 0x044a5262, # upub 'p2wsh-p2sh': 0x024289ef, # Upub 'p2wpkh': 0x045f1cf6, # vpub 'p2wsh': 0x02575483, # Vpub } XPUB_HEADERS_INV = inv_dict(XPUB_HEADERS) BIP44_COIN_TYPE = 1 LN_REALM_BYTE = 1 LN_DNS_SEEDS = [ # TODO investigate this again # 'test.nodes.lightning.directory.', # times out. # 'lseed.bitcoinstats.com.', # ignores REALM byte and returns mainnet peers... ] BLOCK_EXPLORERS = { 'Bitaps.com': ('https://tbtc.bitaps.com/', { 'tx': '', 'addr': '' }), 'BlockCypher.com': ('https://live.blockcypher.com/btc-testnet/', { 'tx': 'tx/', 'addr': 'address/' }), 'Blockchain.info': ('https://www.blockchain.com/btctest/', { 'tx': 'tx/', 'addr': 'address/' }), 'Blockstream.info': ('https://blockstream.info/testnet/', { 'tx': 'tx/', 'addr': 'address/' }), 'smartbit.com.au': ('https://testnet.smartbit.com.au/', { 'tx': 'tx/', 'addr': 'address/' }), 'system default': ('blockchain://000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943/', { 'tx': 'tx/', 'addr': 'address/' }), } @classmethod def get_target(cls, height: int, blockchain) -> int: return 0
class CrowncoinMainnet(AbstractNet, AuxPowMixin, StakeMixin): NAME = 'Crown' NAME_LOWER = 'crown' SHORT_CODE = 'CRW' DATA_DIR = 'crowncoin' OPEN_ALIAS_PREFIX = 'crw' PAYMENT_URI_SCHEME = 'crown' PAYMENT_REQUEST_PKI_TYPE = "dnssec+crw" APPLICATION_PAYMENT_REQUEST_TYPE = 'application/crowncoin-paymentrequest' APPLICATION_PAYMENT_TYPE = 'application/crowncoin-payment' APPLICATION_PAYMENT_ACK_TYPE = 'application/crowncoin-paymentack' BASE_UNITS = {'CRW': 8, 'mCRW': 5, 'uCRW': 2, 'swartz': 0} BASE_UNITS_INVERSE = inv_dict(BASE_UNITS) BASE_UNITS_LIST = ['CRW', 'mCRW', 'uCRW', 'swartz'] TESTNET = False WIF_PREFIX = 0x80 ADDRTYPE_P2PKH = bfh('017507') ADDRTYPE_P2SH = bfh('0174f1') XPRV_HEADERS = { 'standard': 0x0488ade4, } XPRV_HEADERS_INV = inv_dict(XPRV_HEADERS) XPUB_HEADERS = { 'standard': 0x0488b21e, } XPUB_HEADERS_INV = inv_dict(XPUB_HEADERS) BIP44_COIN_TYPE = 72 GENESIS = "0000000085370d5e122f64f4ab19c68614ff3df78c8d13cb814fd7e69a1dc6da" DEFAULT_PORTS = {'t': '50001', 's': '50002'} DEFAULT_SERVERS = read_json('servers/Crowncoin-Mainnet.json', {}) CHECKPOINTS = read_json('checkpoints/Crowncoin-Mainnet.json', []) LN_REALM_BYTE = 0 LN_DNS_SEEDS = [] COINBASE_MATURITY = 100 COIN = 100000000 TOTAL_COIN_SUPPLY_LIMIT = 21000000 SIGNED_MESSAGE_PREFIX = b"\x18Crowncoin Signed Message:\n" DECIMAL_POINT_DEFAULT = 8 # CRW AUXPOW_CHAIN_ID = 0x14 AUXPOW_START_HEIGHT = 45327 BLOCK_VERSION_AUXPOW_BIT = 0x100 DGW_FORK_BLOCK = 1059780 TARGET_TIMESPAN = int(14 * 24 * 60 * 60) TARGET_SPACING = int(60) INTERVAL = int(TARGET_TIMESPAN / TARGET_SPACING) POS_START_HEIGHT = 2330000 MIN_POS_WORK_LIMIT = 0x00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff BLOCK_EXPLORERS = { 'CryptoID.info': ('https://chainz.cryptoid.info/crw/', {'tx': 'tx.dws?', 'addr': 'address.dws?'}), 'system default': ('blockchain:/', {'tx': 'tx/', 'addr': 'address/'}), } # The default Bitcoin frame size limit of 1 MB doesn't work for AuxPoW-based # chains, because those chains' block headers have extra AuxPoW data. # we set a limit of 40 MB so that we have extra wiggle room. MAX_INCOMING_MSG_SIZE = 40_000_000 # in bytes @classmethod def get_target(cls, height: int, blockchain) -> int: index = height // 2016 - 1 if index == -1: return cls.MAX_TARGET if index < len(blockchain.checkpoints): h, t = blockchain.checkpoints[index] return t if height >= cls.DGW_FORK_BLOCK: return cls.get_target_dgw(height, blockchain) return cls.get_target_btc(height, blockchain) @classmethod def get_target_btc(cls, height: int, blockchain) -> int: if not height % cls.INTERVAL == 0: # Get the first block of this retarget period last = blockchain.read_header(height - 1) if not last: raise MissingHeader() return blockchain.bits_to_target(last['bits']) # new target first = blockchain.read_header(height - cls.INTERVAL) last = blockchain.read_header(height - 1) if not first or not last: raise MissingHeader() bits = last.get('bits') target = blockchain.bits_to_target(bits) nActualTimespan = last.get('timestamp') - first.get('timestamp') nActualTimespan = max(nActualTimespan, cls.TARGET_TIMESPAN // 4) nActualTimespan = min(nActualTimespan, cls.TARGET_TIMESPAN * 4) new_target = min(cls.MAX_TARGET, (target * nActualTimespan) // cls.TARGET_TIMESPAN) # not any target can be represented in 32 bits: new_target = blockchain.bits_to_target(blockchain.target_to_bits(new_target)) return new_target @classmethod def get_target_dgw(cls, height: int, blockchain) -> int: # get last solved header current = blockchain.read_header(height - 1) nActualTimespan = 0 lastBlockTime = 0 pastBlocksMin = 24 pastBlocksMax = 24 countBlocks = 0 for i in range(pastBlocksMax): countBlocks += 1 if not current: raise BaseException('header at height: %d is not stored in db' % (height - i - 1)) bits = current.get('bits') if countBlocks <= pastBlocksMin: if countBlocks == 1: past_difficulty_avg = blockchain.bits_to_target(bits) else: past_difficulty_avg = (past_difficulty_avg_prev * countBlocks + blockchain.bits_to_target(bits)) // (countBlocks + 1) past_difficulty_avg_prev = past_difficulty_avg if lastBlockTime > 0: nActualTimespan += lastBlockTime - current.get('timestamp') lastBlockTime = current.get('timestamp') # get previous block current = blockchain.read_header(height - i - 2) target_timespan = countBlocks * cls.TARGET_SPACING nActualTimespan = max(nActualTimespan, target_timespan // 3) nActualTimespan = min(nActualTimespan, target_timespan * 3) new_target = min(cls.MAX_TARGET, (past_difficulty_avg * nActualTimespan) // target_timespan) return new_target @classmethod def hash160_to_b58_address(cls, h160: bytes, addrtype: int) -> str: s = addrtype + h160 return base_encode(s+Hash(s)[0:4], base=58) @classmethod def b58_address_to_hash160(cls, addr): addr = to_bytes(addr, 'ascii') _bytes = base_decode(addr, length=27, base=58) return _bytes[0:3], _bytes[3:23]