From acd414460beb5f26ea71a8411fc9676e9d3d4fa8 Mon Sep 17 00:00:00 2001 From: rc125 Date: Mon, 12 Nov 2018 03:18:27 -0800 Subject: [PATCH] Add SmartCash Support (#640) --- .travis.yml | 1 + electrumx/lib/coins.py | 32 +++++++++++++++++++++- electrumx/lib/tx.py | 15 ++++++++++ electrumx/server/daemon.py | 15 ++++++++++ electrumx/server/session.py | 29 ++++++++++++++++++++ setup.py | 1 + tests/blocks/smartcash_mainnet_200000.json | 16 +++++++++++ tests/lib/test_addresses.py | 2 ++ 8 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 tests/blocks/smartcash_mainnet_200000.json diff --git a/.travis.yml b/.travis.yml index 9439f01..06aad85 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,6 +36,7 @@ install: - pip install groestlcoin_hash - pip install git+https://github.com/goacoincore/neoscrypt - pip install git+https://github.com/motioncrypto/x16r_hash + - pip install pycryptodomex # command to run tests script: - pytest --cov=electrumx diff --git a/electrumx/lib/coins.py b/electrumx/lib/coins.py index 9e838d0..f383982 100644 --- a/electrumx/lib/coins.py +++ b/electrumx/lib/coins.py @@ -45,7 +45,8 @@ from electrumx.lib.script import ScriptPubKey, OpCodes import electrumx.lib.tx as lib_tx import electrumx.server.block_processor as block_proc import electrumx.server.daemon as daemon -from electrumx.server.session import ElectrumX, DashElectrumX +from electrumx.server.session import (ElectrumX, DashElectrumX, + SmartCashElectrumX) Block = namedtuple("Block", "raw header transactions") @@ -2300,3 +2301,32 @@ class CivXTestnet(CivX): return double_sha256(header) else: return hex_str_to_hash(CivXTestnet.GENESIS_HASH) + + +class SmartCash(Coin): + NAME = "SmartCash" + SHORTNAME = "SMART" + NET = "mainnet" + P2PKH_VERBYTE = bytes.fromhex("3f") + P2SH_VERBYTES = [bytes.fromhex("12")] + WIF_BYTE = bytes.fromhex("bf") + 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(cls, header): + '''Given a header return the hash.''' + return cls.HEADER_HASH(header) diff --git a/electrumx/lib/tx.py b/electrumx/lib/tx.py index 6e22dd7..d4c64a8 100644 --- a/electrumx/lib/tx.py +++ b/electrumx/lib/tx.py @@ -623,3 +623,18 @@ class DeserializerDecred(Deserializer): expiry, witness ), tx_hash, self.cursor - start + + +class DeserializerSmartCash(Deserializer): + + @staticmethod + def keccak(data): + from Cryptodome.Hash import keccak + keccak_hash = keccak.new(digest_bits=256) + keccak_hash.update(data) + return keccak_hash.digest() + + def read_tx_and_hash(self): + from electrumx.lib.hash import sha256 + start = self.cursor + return self.read_tx(), sha256(self.binary[start:self.cursor]) diff --git a/electrumx/server/daemon.py b/electrumx/server/daemon.py index 79c4216..9a87099 100644 --- a/electrumx/server/daemon.py +++ b/electrumx/server/daemon.py @@ -457,3 +457,18 @@ class PreLegacyRPCDaemon(LegacyRPCDaemon): async def deserialised_block(self, hex_hash): '''Return the deserialised block with the given hex hash.''' return await self._send_single('getblock', (hex_hash, False)) + + +class SmartCashDaemon(Daemon): + + async def masternode_broadcast(self, params): + '''Broadcast a smartnode to the network.''' + return await self._send_single('smartnodebroadcast', params) + + async def masternode_list(self, params): + '''Return the smartnode status.''' + return await self._send_single('smartnodelist', params) + + async def smartrewards(self, params): + '''Return smartrewards data.''' + return await self._send_single('smartrewards', params) diff --git a/electrumx/server/session.py b/electrumx/server/session.py index af75e08..631e2e9 100644 --- a/electrumx/server/session.py +++ b/electrumx/server/session.py @@ -1430,3 +1430,32 @@ class DashElectrumX(ElectrumX): return [mn for mn in cache if mn['payee'] in payees] else: return cache + + +class SmartCashElectrumX(DashElectrumX): + '''A TCP server that handles incoming Electrum-SMART connections.''' + + def set_request_handlers(self, ptuple): + super().set_request_handlers(ptuple) + self.request_handlers.update({ + 'smartrewards.current': self.smartrewards_current, + 'smartrewards.check': self.smartrewards_check + }) + + async def smartrewards_current(self): + '''Returns the current smartrewards info.''' + result = await self.daemon_request('smartrewards', ['current']) + if result is not None: + return result + return None + + async def smartrewards_check(self, addr): + ''' + Returns the status of an address + + addr: a single smartcash address + ''' + result = await self.daemon_request('smartrewards', ['check', addr]) + if result is not None: + return result + return None diff --git a/setup.py b/setup.py index b8a6ea0..4d934aa 100644 --- a/setup.py +++ b/setup.py @@ -12,6 +12,7 @@ setuptools.setup( # "blake256" package is required to sync Decred network. # "xevan_hash" package is required to sync Xuez network. # "groestlcoin_hash" package is required to sync Groestlcoin network. + # "pycryptodomex" package is required to sync SmartCash network. install_requires=['aiorpcX>=0.10.1,<0.11', 'attrs', 'plyvel', 'pylru', 'aiohttp >= 2'], packages=setuptools.find_packages(include=('electrumx*',)), diff --git a/tests/blocks/smartcash_mainnet_200000.json b/tests/blocks/smartcash_mainnet_200000.json new file mode 100644 index 0000000..5056cbe --- /dev/null +++ b/tests/blocks/smartcash_mainnet_200000.json @@ -0,0 +1,16 @@ +{ + "hash": "000000000000d1772b7e3ffc661133c252faedcc52b3dd186b83da4b2f2f8cbe", + "size": 692, + "height": 200000, + "merkleroot": "f8f490671e499b66a73e3fe37f3b2288b82e3d359fc3c18938f32e9e830928d2", + "tx": [ + "c19c6e1dd5ca9d06b046a2962782293cdd9be39bb006ce65add0ad945c9eaeec", + "0151e788a439caa317dce1cf5a754f0b5bb8639d4f1073e89d3baa450fda5306", + "a4217a9a787b66a597efae52b24e2c88d1700cf5661bac6ed58c718f90a98b97" + ], + "time": 1511678597, + "nonce": 3716569074, + "bits": "1b01c757", + "previousblockhash": "0000000000016e6bcdbe8af532509cf5aaf99e74b8b0346a59d360beb460e0bf", + "block": "02000000bfe060b4be60d3596a34b0b8749ef9aaf59c5032f58abecd6b6e010000000000d22809839e2ef33889c1c39f353d2eb888223b7fe33f3ea7669b491e6790f4f885621a5a57c7011bf25786dd0301000000010000000000000000000000000000000000000000000000000000000000000000ffffffff2703400d03062f503253482f0485621a5a087ffd6961cf0000000d2f6e6f64655374726174756d2f000000000240e6202d040000001976a9145dd99e7cfdee45d47edf9b2d92df27961241145e88ac40412d574f0000001976a9144a7018841fc6003d66b6a1b859e73b4cc3e621b488ac0000000001000000019521d2cde436c42b81158198b2cd8b9d52dc093d4f8465163ecc98a134dd12a6000000006b483045022100ddad79fd8a9fa0ca664ac8e91aa7c8dcc7cad8c4894e1a7d9143de4bdedeef9f022013dfd0605b50d22d2675e21a27255540fa48263ab44801d287a61883ee8074c3012103635fd7668414f4eb1d6088cac789e58709cae9c3c07a00791f415164b67cda4cffffffff0281c03b9e000000001976a9141dc91417504cb86ac5eea49d85a4d3fd51f72db988acbc91e5cb000000001976a914ecdccf8dec8482314050acd84f72d6559a19b30d88ac0000000001000000011a8b6c07eb61bb5e9910de4d31a410a5b69de2bde8a3cb9df599ddaccd373d95000000006c493046022100d1bf91d45a0d53bfad9aa0d226be625f667641fa53661e2cdc21526cf84ede21022100d0cbf38220d789c9b1a5c6288ebfe2e5ddd4ceb5714881d0f43a27d06a6e9649012103133678a3c4d9855f4a25ab318619fe68e0ed67d67c14fa9be678cb561a75f71bffffffff027fd500fc000000001976a914098cd3573bcca56674eb6eeb51fad42ff353945088ac58bda83d000000001976a91456feb1c72217b8f45aa4183da1c81b314a47f5f388ac00000000" +} \ No newline at end of file diff --git a/tests/lib/test_addresses.py b/tests/lib/test_addresses.py index 173f7f2..b1d6bea 100644 --- a/tests/lib/test_addresses.py +++ b/tests/lib/test_addresses.py @@ -67,6 +67,8 @@ addresses = [ "ab72728952c06dfc0f6cf21449dd645422731ec4", "eb3a3155215538d51de7cc"), (coins.TokenPay, "TDE2X28FGtckatxuP3d8s3V726G4TLNHpT", "23b5dd9b7b402388c7a40bc88c261f3178acf30d", "7c7bdf0e0713f3752f4b88"), + (coins.SmartCash, "SQFDM9NtRRmpHebq3H5RA3qpGJfGqp8Xgw", + "206168f5322583ff37f8e55665a4789ae8963532", "b8cb80b26e8932f5b12a7e"), ]