From 6dd704933946bad13f38455af5568b75d2fe11c5 Mon Sep 17 00:00:00 2001 From: FABIANO S CUNHA <30514257+cunhasb@users.noreply.github.com> Date: Thu, 16 Aug 2018 20:57:46 -0400 Subject: [PATCH] Add support for BitcoinGreen (#581) * Add support for BitcoinGreen --- electrumx/lib/coins.py | 145 +++++++++++------- tests/blocks/bitcoingreen_mainnet_10000.json | 14 ++ tests/blocks/bitcoingreen_mainnet_285000.json | 14 ++ tests/lib/test_addresses.py | 4 + tests/server/test_env.py | 47 +++++- 5 files changed, 171 insertions(+), 53 deletions(-) create mode 100644 tests/blocks/bitcoingreen_mainnet_10000.json create mode 100644 tests/blocks/bitcoingreen_mainnet_285000.json diff --git a/electrumx/lib/coins.py b/electrumx/lib/coins.py index c13d64c..8f35d51 100644 --- a/electrumx/lib/coins.py +++ b/electrumx/lib/coins.py @@ -1846,61 +1846,61 @@ class ColossusXT(Coin): class GoByte(Coin): - NAME = "GoByte" - SHORTNAME = "GBX" - NET = "mainnet" - XPUB_VERBYTES = bytes.fromhex("0488B21E") - XPRV_VERBYTES = bytes.fromhex("0488ADE4") - GENESIS_HASH = ('0000033b01055cf8df90b01a14734cae' - '92f7039b9b0e48887b4e33a469d7bc07') - P2PKH_VERBYTE = bytes.fromhex("26") - P2SH_VERBYTES = [bytes.fromhex("0A")] - WIF_BYTE = bytes.fromhex("C6") - TX_COUNT_HEIGHT = 115890 - TX_COUNT = 245030 - TX_PER_BLOCK = 4 - RPC_PORT = 12454 - PEERS = [ - 'electrum1-gbx.polispay.org', - 'electrum2-gbx.polispay.org' - ] - SESSIONCLS = DashElectrumX - DAEMON = daemon.DashDaemon - - @classmethod - def header_hash(cls, header): - '''Given a header return the hash.''' - import neoscrypt - return neoscrypt.getPoWHash(header) + NAME = "GoByte" + SHORTNAME = "GBX" + NET = "mainnet" + XPUB_VERBYTES = bytes.fromhex("0488B21E") + XPRV_VERBYTES = bytes.fromhex("0488ADE4") + GENESIS_HASH = ('0000033b01055cf8df90b01a14734cae' + '92f7039b9b0e48887b4e33a469d7bc07') + P2PKH_VERBYTE = bytes.fromhex("26") + P2SH_VERBYTES = [bytes.fromhex("0A")] + WIF_BYTE = bytes.fromhex("C6") + TX_COUNT_HEIGHT = 115890 + TX_COUNT = 245030 + TX_PER_BLOCK = 4 + RPC_PORT = 12454 + PEERS = [ + 'electrum1-gbx.polispay.org', + 'electrum2-gbx.polispay.org' + ] + SESSIONCLS = DashElectrumX + DAEMON = daemon.DashDaemon + + @classmethod + def header_hash(cls, header): + '''Given a header return the hash.''' + import neoscrypt + return neoscrypt.getPoWHash(header) class Monoeci(Coin): - NAME = "Monoeci" - SHORTNAME = "XMCC" - NET = "mainnet" - XPUB_VERBYTES = bytes.fromhex("0488B21E") - XPRV_VERBYTES = bytes.fromhex("0488ADE4") - GENESIS_HASH = ('0000005be1eb05b05fb45ae38ee9c144' - '1514a65343cd146100a574de4278f1a3') - P2PKH_VERBYTE = bytes.fromhex("32") - P2SH_VERBYTES = [bytes.fromhex("49")] - WIF_BYTE = bytes.fromhex("4D") - TX_COUNT_HEIGHT = 140000 - TX_COUNT = 140000 - TX_PER_BLOCK = 4 - RPC_PORT = 24156 - PEERS = [ - 'electrum1-gbx.polispay.org', - 'electrum2-gbx.polispay.org' - ] - SESSIONCLS = DashElectrumX - DAEMON = daemon.DashDaemon - - @classmethod - def header_hash(cls, header): - '''Given a header return the hash.''' - import x11_hash - return x11_hash.getPoWHash(header) + NAME = "Monoeci" + SHORTNAME = "XMCC" + NET = "mainnet" + XPUB_VERBYTES = bytes.fromhex("0488B21E") + XPRV_VERBYTES = bytes.fromhex("0488ADE4") + GENESIS_HASH = ('0000005be1eb05b05fb45ae38ee9c144' + '1514a65343cd146100a574de4278f1a3') + P2PKH_VERBYTE = bytes.fromhex("32") + P2SH_VERBYTES = [bytes.fromhex("49")] + WIF_BYTE = bytes.fromhex("4D") + TX_COUNT_HEIGHT = 140000 + TX_COUNT = 140000 + TX_PER_BLOCK = 4 + RPC_PORT = 24156 + PEERS = [ + 'electrum1-gbx.polispay.org', + 'electrum2-gbx.polispay.org' + ] + SESSIONCLS = DashElectrumX + DAEMON = daemon.DashDaemon + + @classmethod + def header_hash(cls, header): + '''Given a header return the hash.''' + import x11_hash + return x11_hash.getPoWHash(header) class Minexcoin(EquihashMixin, Coin): @@ -2030,3 +2030,44 @@ class Pivx(Coin): else: import quark_hash return quark_hash.getPoWHash(header) + + +class Bitg(Coin): + + NAME = "BitcoinGreen" + SHORTNAME = "BITG" + NET = "mainnet" + XPUB_VERBYTES = bytes.fromhex("0488b21e") + XPRV_VERBYTES = bytes.fromhex("0488ade4") + P2PKH_VERBYTE = bytes.fromhex("26") + P2SH_VERBYTES = [bytes.fromhex("06")] + WIF_BYTE = bytes.fromhex("2e") + 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 + DAEMON = daemon.DashDaemon + + @classmethod + def header_hash(cls, header): + '''Given a header return the hash.''' + import quark_hash + return quark_hash.getPoWHash(header) + + +class tBitg(Bitg): + SHORTNAME = "tBITG" + NET = "testnet" + XPUB_VERBYTES = bytes.fromhex("043587cf") + XPRV_VERBYTES = bytes.fromhex("04358394") + P2PKH_VERBYTE = bytes.fromhex("62") + P2SH_VERBYTES = [bytes.fromhex("0c")] + WIF_BYTE = bytes.fromhex("6c") + GENESIS_HASH = ( + '000008467c3a9c587533dea06ad9380cded3ed32f9742a6c0c1aebc21bf2bc9b') + RPC_PORT = 19332 diff --git a/tests/blocks/bitcoingreen_mainnet_10000.json b/tests/blocks/bitcoingreen_mainnet_10000.json new file mode 100644 index 0000000..2eedd6a --- /dev/null +++ b/tests/blocks/bitcoingreen_mainnet_10000.json @@ -0,0 +1,14 @@ +{ + "hash": "341452fa379115e62c7b27f9c86376ab8b7aabc4e39337765595edcb97d77930", + "size": 462, + "height": 10000, + "merkleroot": "fe847fdcf26d67b424959c6a9117bb54187eb661653bf2a208b5285eed239195", + "tx": [ + "705e9918f8cb302b9c498396b89f61ce111830512a2809ef2febc315797f777f", "07d211091b51a1e2975ee07ba4933fa59f7aeda0818907bae3a7c497461b5f48" + ], + "time": 1517539297, + "nonce": 0, + "bits": "1b638c5b", + "previousblockhash": "7a9045c58a85b6d6a959721aef60ce5963897559a423e0e17ac1d34508a2ee53", + "block": "0400000053eea20845d3c17ae1e023a45975896359ce60ef1a7259a9d6b6858ac545907a959123ed5e28b508a2f23b6561b67e1854bb17916a9c9524b4676df2dc7f84fee1cf735a5b8c631b000000000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff050210270101ffffffff0100000000000000000000000000010000000145ecb9083be84c146b1c96b88bf5157fe1771f7d6739bd137855c268e03da4c3020000006b4830450221009b4f8a1c8968c77192d38a538764a1fa5b33f9aef60e85c2157271759008033702202673c800cf8ce94259c0a06b9b093c9d1a716477ef9a1cb7c49c3c73ce7bbd880121023df508324112d8aa326d0539d741bf5f1f9dfc37d9f62b9b4574d76a1bd9600affffffff03000000000000000000005ed0b2000000002321023df508324112d8aa326d0539d741bf5f1f9dfc37d9f62b9b4574d76a1bd9600aac80e9fd97000000001976a914ee49dbdba7d30e659b93dde35d52c961ecbd186b88ac0000000046304402200320cb9881b72a30e81f5b2bfddc5bc404a3af8ef9220da8314896d7d025b5a0022070d9438034f84550b3a42fcaf86e7d186634956668b07702fa62d9db05b89366" +} \ No newline at end of file diff --git a/tests/blocks/bitcoingreen_mainnet_285000.json b/tests/blocks/bitcoingreen_mainnet_285000.json new file mode 100644 index 0000000..071ef25 --- /dev/null +++ b/tests/blocks/bitcoingreen_mainnet_285000.json @@ -0,0 +1,14 @@ +{ + "hash": "9b0276d83dff1883badf00a3d4cc2470cb8b5cb88fc8f7e506116d170ca13e25", + "size": 429, + "height": 285000, + "merkleroot": "ceac2a8b68bcfb5670c5acbeeca791ddfc4ed03b01beefb9e5e2d0f50462c8cb", + "tx": [ + "5f381284dd7a496e1ebbabad5e870b28f108cc5bdc0ca8a93b54adb2611d16a3", "703b3f9a312c3eac763f7391905cfabba3faeea89f31b2952d287ab56c69965d" + ], + "time": 1534140284, + "nonce": 0, + "bits": "1b31a5bd", + "previousblockhash": "51670aa1f4b4564258c318edb8f2b1f4e7945154a138ac4516ee2d14e6939fed", + "block": "04000000ed9f93e6142dee1645ac38a1545194e7f4b1f2b8ed18c3584256b4f4a10a6751cbc86204f5d0e2e5b9efbe013bd04efcdd91a7ecbeacc57056fbbc688b2aacce7c1f715bbda5311b000000000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff06034859040101ffffffff01000000000000000000000000000100000001871709454e15ee7ee23d602808a8b24a8f46ffdd883c788124827f78afd2292e0100000049483045022100db102575ef2f04151d302fd69ea1b5e5a45eb58e330d3fd0a1b42b3a688187dc02204f8380379afb4dbb05e6961add378a027dff5d0252d948b3bd2b89a9dc09856301ffffffff03000000000000000000cb8488150c000000232102d8e7ecc69382c4f201d76356074d79ef1378368cdffa01aff2fa21693e1a4933ac80f8a932000000001976a914f82aff4e5ed1a6b8d310145284371421e921c1a288ac000000004630440220646d7ab39036a29ae9e27805aa00d9dfcf1640601225cdd23daf9f8232f3f5eb02207a7bf880ffad041240bf01c304dc660796de4719a1827c9c2eb8bc84c3c01c29" +} \ No newline at end of file diff --git a/tests/lib/test_addresses.py b/tests/lib/test_addresses.py index a53da61..de30892 100644 --- a/tests/lib/test_addresses.py +++ b/tests/lib/test_addresses.py @@ -53,6 +53,10 @@ addresses = [ "f0b4e85100aee1a996f22915eb3c3f764d53779a", "a03c1a27de9ac3b3122e8d"), (coins.Groestlcoin, "FY7vmDL7FZGACwqVNx5p4fVaGghojWM5AF", "206168f5322583ff37f8e55665a4789ae8963532", "b8cb80b26e8932f5b12a7e"), + (coins.Bitg, "GP1vBChXjjbaKwMcoPGB4T8cZLXWCe2wLV", + "38bc968f95157bb7446feb1a7d75f2791fc8cf91", "4c7332cd142b788dd89241"), + (coins.Bitg, "GaXGkXrm4dK1CYfSWvKubKgMcrYN59BZGF", + "b6f335a20a887f03a1d8a5c701f967c35d9b45c4", "383b20a90a9109531ccd7e") ] diff --git a/tests/server/test_env.py b/tests/server/test_env.py index 37f5640..6afd348 100644 --- a/tests/server/test_env.py +++ b/tests/server/test_env.py @@ -19,16 +19,19 @@ base_environ = { 'COIN': 'BitcoinCash', } + def setup_base_env(): os.environ.clear() os.environ.update(base_environ) + def assert_required(env_var): setup_base_env() os.environ.pop(env_var, None) with pytest.raises(Env.Error): Env() + def assert_default(env_var, attr, default): setup_base_env() e = Env() @@ -37,6 +40,7 @@ def assert_default(env_var, attr, default): e = Env() assert getattr(e, attr) == 'foo' + def assert_integer(env_var, attr, default=''): if default != '': e = Env() @@ -49,6 +53,7 @@ def assert_integer(env_var, attr, default=''): e = Env() assert getattr(e, attr) == value + def assert_boolean(env_var, attr, default): e = Env() assert getattr(e, attr) == default @@ -59,22 +64,26 @@ def assert_boolean(env_var, attr, default): e = Env() assert getattr(e, attr) == False + def test_minimal(): setup_base_env() Env() + def test_DB_DIRECTORY(): assert_required('DB_DIRECTORY') setup_base_env() e = Env() assert e.db_dir == BASE_DB_DIR + def test_DAEMON_URL(): assert_required('DAEMON_URL') setup_base_env() e = Env() assert e.daemon_url == BASE_DAEMON_URL + def test_COIN_NET(): '''Test COIN and NET defaults and redirection.''' setup_base_env() @@ -103,10 +112,19 @@ def test_COIN_NET(): os.environ['NET'] = 'regtest' e = Env() assert e.coin == lib_coins.BitcoinGoldRegtest + os.environ.pop('NET') + os.environ['COIN'] = ' BitcoinGreen ' + e = Env() + assert e.coin == lib_coins.Bitg + os.environ['NET'] = 'mainnet' + e = Env() + os.environ.pop('NET') + def test_CACHE_MB(): assert_integer('CACHE_MB', 'cache_MB', 1200) + def test_HOST(): assert_default('HOST', 'host', 'localhost') os.environ['HOST'] = '' @@ -119,6 +137,7 @@ def test_HOST(): e = Env() assert e.cs_host(for_rpc=False) == ['192.168.0.1', '23.45.67.89'] + def test_RPC_HOST(): assert_default('RPC_HOST', 'rpc_host', 'localhost') os.environ['RPC_HOST'] = '' @@ -129,13 +148,16 @@ def test_RPC_HOST(): e = Env() assert e.cs_host(for_rpc=True) == ['127.0.0.1', '::1'] + def test_REORG_LIMIT(): assert_integer('REORG_LIMIT', 'reorg_limit', lib_coins.BitcoinCash.REORG_LIMIT) + def test_TCP_PORT(): assert_integer('TCP_PORT', 'tcp_port', None) + def test_SSL_PORT(): # Requires both SSL_CERTFILE and SSL_KEYFILE to be set os.environ['SSL_PORT'] = '50002' @@ -151,27 +173,35 @@ def test_SSL_PORT(): os.environ.pop('SSL_PORT') assert_integer('SSL_PORT', 'ssl_port', None) + def test_RPC_PORT(): assert_integer('RPC_PORT', 'rpc_port', 8000) + def test_MAX_SUBSCRIPTIONS(): assert_integer('MAX_SUBSCRIPTIONS', 'max_subscriptions', 10000) + def test_LOG_SESSIONS(): assert_integer('LOG_SESSIONS', 'log_sessions', 3600) + def test_DONATION_ADDRESS(): assert_default('DONATION_ADDRESS', 'donation_address', '') + def test_DB_ENGINE(): assert_default('DB_ENGINE', 'db_engine', 'leveldb') + def test_MAX_SEND(): assert_integer('MAX_SEND', 'max_send', 1000000) + def test_MAX_SUBS(): assert_integer('MAX_SUBS', 'max_subs', 250000) + def test_MAX_SESSIONS(): too_big = 1000000 os.environ['MAX_SESSIONS'] = str(too_big) @@ -179,15 +209,19 @@ def test_MAX_SESSIONS(): assert e.max_sessions < too_big # Cannot test default as it may be lowered by the open file limit cap + def test_MAX_SESSION_SUBS(): assert_integer('MAX_SESSION_SUBS', 'max_session_subs', 50000) + def test_BANDWIDTH_LIMIT(): assert_integer('BANDWIDTH_LIMIT', 'bandwidth_limit', 2000000) + def test_SESSION_TIMEOUT(): assert_integer('SESSION_TIMEOUT', 'session_timeout', 600) + def test_BANNER_FILE(): e = Env() assert e.banner_file is None @@ -201,6 +235,7 @@ def test_BANNER_FILE(): assert e.banner_file == 'banner_file' assert e.tor_banner_file == 'tor_banner_file' + def test_EVENT_LOOP_POLICY(): e = Env() assert e.loop_policy is None @@ -214,9 +249,11 @@ def test_EVENT_LOOP_POLICY(): pass del os.environ['EVENT_LOOP_POLICY'] + def test_ANON_LOGS(): assert_boolean('ANON_LOGS', 'anon_logs', False) + def test_PEER_DISCOVERY(): e = Env() assert e.peer_discovery == Env.PD_ON @@ -230,18 +267,23 @@ def test_PEER_DISCOVERY(): e = Env() assert e.peer_discovery == Env.PD_SELF + def test_PEER_ANNOUNCE(): assert_boolean('PEER_ANNOUNCE', 'peer_announce', True) + def test_FORCE_PROXY(): assert_boolean('FORCE_PROXY', 'force_proxy', False) + def test_TOR_PROXY_HOST(): assert_default('TOR_PROXY_HOST', 'tor_proxy_host', 'localhost') + def test_TOR_PROXY_PORT(): assert_integer('TOR_PROXY_PORT', 'tor_proxy_port', None) + def test_clearnet_identity(): os.environ['REPORT_TCP_PORT'] = '456' e = Env() @@ -296,6 +338,7 @@ def test_clearnet_identity(): assert ident.ssl_port == 457 assert ident.nick_suffix == '' + def test_tor_identity(): tor_host = 'something.onion' os.environ.pop('REPORT_HOST', None) @@ -342,6 +385,7 @@ def test_tor_identity(): assert ident.tcp_port == 234 assert ident.ssl_port == 432 + def test_ban_versions(): e = Env() assert e.drop_client is None @@ -352,6 +396,7 @@ def test_ban_versions(): assert e.drop_client.match("1.2.3_buggy_client") assert e.drop_client.match("1.3.0_good_client") is None + def test_coin_class_provided(): e = Env(lib_coins.BitcoinCash) - assert e.coin == lib_coins.BitcoinCash \ No newline at end of file + assert e.coin == lib_coins.BitcoinCash