Add SmartCash Support (#640)
This commit is contained in:
parent
cf92ece302
commit
acd414460b
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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])
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
1
setup.py
1
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*',)),
|
||||
|
||||
16
tests/blocks/smartcash_mainnet_200000.json
Normal file
16
tests/blocks/smartcash_mainnet_200000.json
Normal file
@ -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"
|
||||
}
|
||||
@ -67,6 +67,8 @@ addresses = [
|
||||
"ab72728952c06dfc0f6cf21449dd645422731ec4", "eb3a3155215538d51de7cc"),
|
||||
(coins.TokenPay, "TDE2X28FGtckatxuP3d8s3V726G4TLNHpT",
|
||||
"23b5dd9b7b402388c7a40bc88c261f3178acf30d", "7c7bdf0e0713f3752f4b88"),
|
||||
(coins.SmartCash, "SQFDM9NtRRmpHebq3H5RA3qpGJfGqp8Xgw",
|
||||
"206168f5322583ff37f8e55665a4789ae8963532", "b8cb80b26e8932f5b12a7e"),
|
||||
]
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user