Browse Source

Add Decred(DCR) (#402)

patch-2
cipherzzz 7 years ago
committed by Neil
parent
commit
c26227413e
  1. 1
      .travis.yml
  2. 52
      lib/coins.py
  3. 103
      lib/tx.py
  4. 1
      setup.py
  5. 30
      tests/blocks/decred_mainnet_200000.json
  6. 17
      tests/blocks/decred_testnet_200000.json

1
.travis.yml

@ -20,6 +20,7 @@ install:
- pip install tribus-hash - pip install tribus-hash
- pip install pytest-cov - pip install pytest-cov
- pip install pylru - pip install pylru
- pip install blake256
# command to run tests # command to run tests
script: pytest --cov=server --cov=lib --cov=wallet script: pytest --cov=server --cov=lib --cov=wallet
# Dont report coverage from nightly # Dont report coverage from nightly

52
lib/coins.py

@ -35,6 +35,7 @@ import re
import struct import struct
from decimal import Decimal from decimal import Decimal
from hashlib import sha256 from hashlib import sha256
from functools import partial
import lib.util as util import lib.util as util
from lib.hash import Base58, hash160, double_sha256, hash_to_str from lib.hash import Base58, hash160, double_sha256, hash_to_str
@ -1420,3 +1421,54 @@ class BitcoinAtom(Coin):
'''Return the block header bytes''' '''Return the block header bytes'''
deserializer = cls.DESERIALIZER(block) deserializer = cls.DESERIALIZER(block)
return deserializer.read_header(height, cls.BASIC_HEADER_SIZE) return deserializer.read_header(height, cls.BASIC_HEADER_SIZE)
class Decred(Coin):
NAME = "Decred"
SHORTNAME = "DCR"
NET = "mainnet"
XPUB_VERBYTES = bytes('dpub', 'utf-8')
XPRV_VERBYTES = bytes('dprv', 'utf-8')
P2PKH_VERBYTE = bytes('Ds', 'utf-8')
P2SH_VERBYTES = [bytes('Dc', 'utf-8')]
WIF_BYTE = bytes('Pm', 'utf-8')
GENESIS_HASH = ('298e5cc3d985bfe7f81dc135f360abe089edd4396b86d2de66b0cef42b21d980')
DESERIALIZER = lib_tx.DeserializerDecred
ENCODE_CHECK = partial(Base58.encode_check, hash_fn=lib_tx.DeserializerDecred.blake256)
DECODE_CHECK = partial(Base58.decode_check, hash_fn=lib_tx.DeserializerDecred.blake256)
HEADER_HASH = lib_tx.DeserializerDecred.blake256
BASIC_HEADER_SIZE = 180
ALLOW_ADVANCING_ERRORS = True
TX_COUNT = 217380620
TX_COUNT_HEIGHT = 218875
TX_PER_BLOCK = 1000
RPC_PORT = 9109
@classmethod
def header_hash(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):
NAME = "Decred"
NET = "testnet"
XPUB_VERBYTES = bytes('tpub', 'utf-8')
XPRV_VERBYTES = bytes('tprv', 'utf-8')
P2PKH_VERBYTE = bytes('Ts', 'utf-8')
P2SH_VERBYTES = [bytes('Tc', 'utf-8')]
WIF_BYTE = bytes('Pt', 'utf-8')
GENESIS_HASH = ('4261602a9d07d80ad47621a64ba6a07754902e496777edc4ff581946bd7bc29c')
TX_COUNT = 3176305
TX_COUNT_HEIGHT = 254198
TX_PER_BLOCK = 1000
RPC_PORT = 19119

103
lib/tx.py

@ -401,3 +401,106 @@ class DeserializerBitcoinAtom(DeserializerSegWit):
if height >= self.FORK_BLOCK_HEIGHT: if height >= self.FORK_BLOCK_HEIGHT:
header_len += 4 # flags header_len += 4 # flags
return self._read_nbytes(header_len) return self._read_nbytes(header_len)
# Decred
class TxInputDcr(namedtuple("TxInput", "prev_hash prev_idx tree sequence")):
'''Class representing a Decred transaction input.'''
ZERO = bytes(32)
MINUS_1 = 4294967295
@cachedproperty
def is_coinbase(self):
# The previous output of a coin base must have a max value index and a
# zero hash.
return (self.prev_hash == TxInputDcr.ZERO and
self.prev_idx == TxInputDcr.MINUS_1)
def __str__(self):
prev_hash = hash_to_str(self.prev_hash)
return ("Input({}, {:d}, tree={}, sequence={:d})"
.format(prev_hash, self.prev_idx, self.tree, self.sequence))
class TxOutputDcr(namedtuple("TxOutput", "value version pk_script")):
'''Class representing a transaction output.'''
pass
class TxDcr(namedtuple("Tx", "version inputs outputs locktime expiry "
"witness")):
'''Class representing transaction that has a time field.'''
@cachedproperty
def is_coinbase(self):
return self.inputs[0].is_coinbase
class DeserializerDecred(Deserializer):
@staticmethod
def blake256(data):
from blake256.blake256 import blake_hash
return blake_hash(data)
def read_tx_block(self):
'''Returns a list of (deserialized_tx, tx_hash) pairs.'''
read_tx = self.read_tx
txs = [read_tx() for _ in range(self._read_varint())]
stxs = [read_tx() for _ in range(self._read_varint())]
return txs + stxs
def _read_inputs(self):
read_input = self._read_input
return [read_input() for i in range(self._read_varint())]
def _read_input(self):
return TxInputDcr(
self._read_nbytes(32), # prev_hash
self._read_le_uint32(), # prev_idx
self._read_byte(), # tree
self._read_le_uint32(), # sequence
)
def _read_outputs(self):
read_output = self._read_output
return [read_output() for _ in range(self._read_varint())]
def _read_output(self):
return TxOutputDcr(
self._read_le_int64(), # value
self._read_le_uint16(), # version
self._read_varbytes(), # pk_script
)
def _read_witness(self, fields):
read_witness_field = self._read_witness_field
assert fields == self._read_varint()
return [read_witness_field() for _ in range(fields)]
def _read_witness_field(self):
value_in = self._read_le_int64()
block_height = self._read_le_uint32()
block_index = self._read_le_uint32()
script = self._read_varbytes()
return value_in, block_height, block_index, script
def read_tx(self):
start = self.cursor
version = self._read_le_int32()
assert version == 1 # TODO check other versions for segwit
inputs = self._read_inputs()
outputs = self._read_outputs()
locktime = self._read_le_uint32()
expiry = self._read_le_uint32()
no_witness_tx = b'\x01\x00\x01\x00' + self.binary[start+4:self.cursor]
witness = self._read_witness(len(inputs))
return TxDcr(
version,
inputs,
outputs,
locktime,
expiry,
witness
), DeserializerDecred.blake256(no_witness_tx)

1
setup.py

@ -10,6 +10,7 @@ setuptools.setup(
# via environment variables, in which case I've tested with 15.0.4 # via environment variables, in which case I've tested with 15.0.4
# "x11_hash" package (1.4) is required to sync DASH network. # "x11_hash" package (1.4) is required to sync DASH network.
# "tribus_hash" package is required to sync Denarius network. # "tribus_hash" package is required to sync Denarius network.
# "blake256" package is required to sync Decred network.
install_requires=['plyvel', 'pylru', 'aiohttp >= 1'], install_requires=['plyvel', 'pylru', 'aiohttp >= 1'],
packages=setuptools.find_packages(exclude=['tests']), packages=setuptools.find_packages(exclude=['tests']),
description='ElectrumX Server', description='ElectrumX Server',

30
tests/blocks/decred_mainnet_200000.json

File diff suppressed because one or more lines are too long

17
tests/blocks/decred_testnet_200000.json

@ -0,0 +1,17 @@
{
"hash": "0000000003416ee936e24e3d8ebb0ae12cc9cd397df61346f2805642676291ae",
"size": 1637,
"height": 200000,
"merkleroot": "560d636172de028d728723b41428eb51acb4e969caf54f50f0de19f14a66fb1e",
"tx": [
"42fb258edd91d3b4aeea43f2451311b1045e3d0f935491301e03377eb86b1c46",
"9b1e326156e1426d1b2c32d711e660c936f53fcdf90de3ea4f8ae18c695751e0",
"017ac016d59cbc1b381ae71f61173bf9b5eaf85e338f2b81df73f88574bc7fa6",
"a15ddc52b33346ddb22005eaf622336d0f56856f598e1068d1fba280d9cf0408"
],
"time": 1513807068,
"nonce": 4094753344,
"bits": "1c038167",
"previousblockhash": "0000000001c195bb55127867a4dbeb9385fc14113db92a787ccd8c64d4bab58f",
"block": "060000008fb5bad4648ccd7c782ab93d1114fc8593ebdba467781255bb95c101000000001efb664af119def0504ff5ca69e9b4ac51eb2814b42387728d02de7261630d56778f843a51d3aa5d44dd17c5f35a0b163d925b9ce2dc7dfb25cb1534184cce4e01005768179ecf0803000000e41200006781031cbcf9645901000000400d030065060000dcdc3a5a40fa10f43ffde600cc7b6b00000000000000000000000000000000000000000000000000060000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff03b0d76703000000000000144fa6cbd0dbe5ec407fe4c8ad374e667771fa0d4400000000000000000000266a24400d03000000000000000000000000000000000000000000000000008ca3582a0607db7b260e6f140000000000001976a9149d8e8bdc618035be32a14ab752af2e331f9abf3688ac000000000000000001d5e5d6170000000000000000ffffffff0800002f646372642f0301000000020000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffffab941af0b55cb4fd9a936b4b02cd052e9821b307c11389d3a3e68b40911b9c360000000001ffffffff0400000000000000000000266a248fb5bad4648ccd7c782ab93d1114fc8593ebdba467781255bb95c101000000003f0d030000000000000000000000086a060500060000003dc040000000000000001abb76a9147f686bc0e548bbb92f487db6da070e43a341172888ac3cdc96d60000000000001abb76a9149d8e8bdc618035be32a14ab752af2e331f9abf3688ac000000000000000002b0d767030000000000000000ffffffff020000cac46fd300000000260b03000d0000009047304402203a4a29b406b8eac0ac9adbbe818a28795cada504e83a46aa3e9c41cbfa014f700220310017fb5c5b5cc27d4b22f0867c324badf7a0b3953a274d95d1295e447f136d0147512102fe82f22f2e5bc1be0b67d85afef87329fc1c4512f30a47ce459c78bd7502ba9821022cf2f038dbb85f0a35fed9ac147e58d9ee85a80f8827085f51ef4129a02d458652ae01000000020000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff171c0027204501f9572b19306e8fe6813b00391aaec26d295fabbb449fa245e00000000001ffffffff0400000000000000000000266a248fb5bad4648ccd7c782ab93d1114fc8593ebdba467781255bb95c101000000003f0d030000000000000000000000086a060500060000005f6341000000000000001abb76a9147f686bc0e548bbb92f487db6da070e43a341172888ac38a085010100000000001abb76a9149d8e8bdc618035be32a14ab752af2e331f9abf3688ac000000000000000002b0d767030000000000000000ffffffff020000e82b5ffe00000000e40603000500000090473044022060f6d935b0385d55a12899c48fa18e7e938d819874c3fe72924d665122fa95c30220566fcc424cf25f772007cff3b0a0f6f99dbf5b197ac26c1b67347a2dccb152bb0147512102fe82f22f2e5bc1be0b67d85afef87329fc1c4512f30a47ce459c78bd7502ba9821022cf2f038dbb85f0a35fed9ac147e58d9ee85a80f8827085f51ef4129a02d458652ae01000000020000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff21cd5bfc8082569d5b317be8cf67d6b36dbb4711a5f69dc25aea0d6c7e319e4b0000000001ffffffff0400000000000000000000266a248fb5bad4648ccd7c782ab93d1114fc8593ebdba467781255bb95c101000000003f0d030000000000000000000000086a060500060000005f6341000000000000001abb76a9147f686bc0e548bbb92f487db6da070e43a341172888ac711c961c0100000000001abb76a9149d8e8bdc618035be32a14ab752af2e331f9abf3688ac000000000000000002b0d767030000000000000000ffffffff02000021a86f190100000029040300060000009148304502210098a4987ba360e1aea04de1ff77c1f5dd646b7dd1b00136ca58db005248e4451b022001b87cf0bb13bef9e09a48cfa88d5b9f6fc07af95cdc75b4e9f67c040541737a0147512102fe82f22f2e5bc1be0b67d85afef87329fc1c4512f30a47ce459c78bd7502ba9821022cf2f038dbb85f0a35fed9ac147e58d9ee85a80f8827085f51ef4129a02d458652ae"
}
Loading…
Cancel
Save