Browse Source

Equihash POW abstraction and Bitcoin Gold support (#311)

* Extract the Equihash mixin from Zcash

The extracted EquihashMixin and DeserializerEquihash are used when
the Equihash POW support is needed but the Zcash transaction parsing
is not.

* Add Bitcoin Gold support

* Minor formatting fixing
patch-1
John L. Jegutanis 7 years ago
committed by Neil
parent
commit
f3fea9f8ee
  1. 85
      lib/coins.py
  2. 25
      lib/tx.py
  3. 15
      tests/blocks/bitcoingold_mainnet_499912.json
  4. 15
      tests/blocks/bitcoingold_mainnet_80000.json

85
lib/coins.py

@ -318,6 +318,33 @@ class AuxPowMixin(object):
return deserializer.read_header(height, cls.BASIC_HEADER_SIZE)
class EquihashMixin(object):
STATIC_BLOCK_HEADERS = False
BASIC_HEADER_SIZE = 140 # Excluding Equihash solution
DESERIALIZER = lib_tx.DeserializerEquihash
@classmethod
def electrum_header(cls, header, height):
version, = struct.unpack('<I', header[:4])
timestamp, bits = struct.unpack('<II', header[100:108])
return {
'block_height': height,
'version': version,
'prev_block_hash': hash_to_str(header[4:36]),
'merkle_root': hash_to_str(header[36:68]),
'timestamp': timestamp,
'bits': bits,
'nonce': hash_to_str(header[108:140]),
}
@classmethod
def block_header(cls, block, height):
'''Return the block header bytes'''
deserializer = cls.DESERIALIZER(block)
return deserializer.read_header(height, cls.BASIC_HEADER_SIZE)
class BitcoinMixin(object):
SHORTNAME = "BTC"
NET = "mainnet"
@ -372,6 +399,29 @@ class BitcoinSegwit(BitcoinMixin, Coin):
]
class BitcoinGold(EquihashMixin, BitcoinMixin, Coin):
NAME = "BitcoinGold"
SHORTNAME = "BTG"
FORK_HEIGHT = 491407
P2PKH_VERBYTE = bytes.fromhex("26")
P2SH_VERBYTES = [bytes.fromhex("17")]
DESERIALIZER = lib_tx.DeserializerEquihashSegWit
TX_COUNT = 265026255
TX_COUNT_HEIGHT = 499923
TX_PER_BLOCK = 50
REORG_LIMIT = 1000
@classmethod
def header_hash(cls, header):
'''Given a header return hash'''
height, = struct.unpack('<I', header[68:72])
if height >= cls.FORK_HEIGHT:
return double_sha256(header)
else:
return double_sha256(header[:68] + header[100:112])
class Emercoin(Coin):
NAME = "Emercoin"
SHORTNAME = "EMC"
@ -447,6 +497,11 @@ class BitcoinSegwitTestnet(BitcoinTestnetMixin, Coin):
]
class BitcoinGoldTestnet(BitcoinTestnetMixin, BitcoinGold):
NAME = "BitcoinGold"
FORK_HEIGHT = 1210320
class BitcoinSegwitRegtest(BitcoinSegwitTestnet):
NAME = "BitcoinSegwit"
NET = "regtest"
@ -561,6 +616,7 @@ class ViacoinTestnet(Viacoin):
'vialectrum.bysh.me s t',
]
class ViacoinTestnetSegWit(ViacoinTestnet):
NET = "testnet-segwit"
DESERIALIZER = lib_tx.DeserializerSegWit
@ -785,7 +841,7 @@ class FairCoin(Coin):
}
class Zcash(Coin):
class Zcash(EquihashMixin, Coin):
NAME = "Zcash"
SHORTNAME = "ZEC"
NET = "mainnet"
@ -794,8 +850,6 @@ class Zcash(Coin):
WIF_BYTE = bytes.fromhex("80")
GENESIS_HASH = ('00040fe8ec8471911baa1db1266ea15d'
'd06b4a8a5c453883c000b031973dce08')
STATIC_BLOCK_HEADERS = False
BASIC_HEADER_SIZE = 140 # Excluding Equihash solution
DESERIALIZER = lib_tx.DeserializerZcash
TX_COUNT = 329196
TX_COUNT_HEIGHT = 68379
@ -805,27 +859,6 @@ class Zcash(Coin):
RPC_PORT = 8232
REORG_LIMIT = 800
@classmethod
def electrum_header(cls, header, height):
version, = struct.unpack('<I', header[:4])
timestamp, bits = struct.unpack('<II', header[100:108])
return {
'block_height': height,
'version': version,
'prev_block_hash': hash_to_str(header[4:36]),
'merkle_root': hash_to_str(header[36:68]),
'timestamp': timestamp,
'bits': bits,
'nonce': hash_to_str(header[108:140]),
}
@classmethod
def block_header(cls, block, height):
'''Return the block header bytes'''
deserializer = cls.DESERIALIZER(block)
return deserializer.read_header(height, cls.BASIC_HEADER_SIZE)
class Einsteinium(Coin):
NAME = "Einsteinium"
@ -914,7 +947,6 @@ class Bitbay(Coin):
return cls.HEADER_HASH(header)
class Peercoin(Coin):
NAME = "Peercoin"
SHORTNAME = "PPC"
@ -1035,6 +1067,7 @@ class Fujicoin(Coin):
RPC_PORT = 3776
REORG_LIMIT = 1000
class Neblio(Coin):
NAME = "Neblio"
SHORTNAME = "NEBL"
@ -1067,6 +1100,7 @@ class Neblio(Coin):
else:
return cls.HEADER_HASH(header)
class Bitzeny(Coin):
NAME = "Bitzeny"
SHORTNAME = "ZNY"
@ -1087,6 +1121,7 @@ class Bitzeny(Coin):
RPC_PORT = 9252
REORG_LIMIT = 1000
class CanadaeCoin(AuxPowMixin, Coin):
NAME = "CanadaeCoin"
SHORTNAME = "CDN"

25
lib/tx.py

@ -67,6 +67,7 @@ class TxInput(namedtuple("TxInput", "prev_hash prev_idx script sequence")):
class TxOutput(namedtuple("TxOutput", "value pk_script")):
pass
class Deserializer(object):
'''Deserializes blocks into transactions.
@ -261,15 +262,7 @@ class DeserializerAuxPowSegWit(DeserializerSegWit, DeserializerAuxPow):
pass
class TxJoinSplit(namedtuple("Tx", "version inputs outputs locktime")):
'''Class representing a JoinSplit transaction.'''
@cachedproperty
def is_coinbase(self):
return self.inputs[0].is_coinbase if len(self.inputs) > 0 else False
class DeserializerZcash(Deserializer):
class DeserializerEquihash(Deserializer):
def read_header(self, height, static_header_size):
'''Return the block header bytes'''
start = self.cursor
@ -281,6 +274,20 @@ class DeserializerZcash(Deserializer):
self.cursor = start
return self._read_nbytes(header_end)
class DeserializerEquihashSegWit(DeserializerSegWit, DeserializerEquihash):
pass
class TxJoinSplit(namedtuple("Tx", "version inputs outputs locktime")):
'''Class representing a JoinSplit transaction.'''
@cachedproperty
def is_coinbase(self):
return self.inputs[0].is_coinbase if len(self.inputs) > 0 else False
class DeserializerZcash(DeserializerEquihash):
def read_tx(self):
start = self.cursor
base_tx = TxJoinSplit(

15
tests/blocks/bitcoingold_mainnet_499912.json

@ -0,0 +1,15 @@
{
"hash": "000000000dae8d873f300e1798e5c30353c831d7bdc048e559889f015dec4c25",
"size": 1889,
"height": 499912,
"merkleroot": "e29a320d6e2a00b49002acc6149f04d2aa90b4e37f80840f4ea26fb3b4949559",
"tx": [
"885c342d554e2bd9ba0b3b1b17da4d04fe88957e9d06ca922a26fb67c9ad3b91",
"a4c7785c6b5b6a1125af20e0bd01824919ed67730442ded5bc5ff5c1cb4f4dcd"
],
"time": 1510594713,
"nonce": "01000000000000000000000003cfdc2609e4ff77000000000000000077ffe40a",
"bits": "1c14f7c1",
"previousblockhash": "00000000066db5fd7315c9dd8a260c1c38876e8f4dfa83904f4a682d5532f2ac",
"block": "00000020acf232552d684a4f9083fa4d8f6e87381c0c268addc91573fdb56d0600000000599594b4b36fa24e0f84807fe3b490aad2049f14c6ac0290b4002a6e0d329ae2c8a007000000000000000000000000000000000000000000000000000000000099d8095ac1f7141c0ae4ff77000000000000000077ffe40926dccf03000000000000000000000001fd40050124e0c3ae16f421a630c3d7f8762a596d96be0e9b114209262ae670a593b2250650fb467a7b6b3687fa111b0b1cf9c48177375dc597f449f549eff7d985721ede1177aece8d7bf77ed2ea44730751397eaa135b19b746c94058ae27d7ffd3f1a1ce1c62b0c51bab5e20af95eb6b159ddba38de547b6639ed5a4e952fb421caddf9aa6a8a5f56bc43622a0692f6aaf8816cafa1dc379c05895ffdd39d33310a275ccde7fce7a42b20329a13bd492010af88c04a016707caa4c00543b780460c7f55b8a962b3543e58e843a418689911a6e902d069461885911a5704338389f46906ae0f25b652e2dd2d6002b11394ceb6cf70587fae4f5eb162fa52105291dd53121423b7cc53217ae213b173464be083420c6c9df0a8d22031c17d3ffd35c4ac94335deb140062c91313d0ee1d3e883210d115c0dac5a934d6d7f47e5cfaaa8d4da88de3665b75f2fba46d7e29f8a8a01c019f20b9ff8eddc5701e5baf114ab5b9ebc1d5842c4e72d809c16b9a535c5dd15fd39adc628de07d803c4b16de64c7fd8dd421639aa3708060b4977e4dc05615045cfebcec5f608b2c15258ca30ce5dfb4a3305f4e95efa20e35335e820f92f4445e8d4c7f1602d108ae0da6b0af1dcf5ab41c1b750df398c69175c7d18aea4aa23ee929bf98ef7c7e8c62826f3a51fd7475f882bc09960b7d544a2b6d8f576e2ea545a1b9c9a0321c56e749018eb6e299df303f0d5db9db47ea5d51b58d72330d89a06f974e2417da13af914cfff768d1222a6725ec4982bd215d30079ed7fa28ade793b8a24f534f647e2b0c3e34219a6e6da2c6787331c66230ce2a0d3244c753cfb8890f51f66915d5d66d6d19f0f8f0f92eec9b1a5704292941146d476ae7bff4f6c2f268ae8fe97720ac2b288646e56b6a2cbd87e2ee43e6e8dde25a36a6bd0e618c3b6520822435d1d669f015a3e7b3f4b54036459831d793c230de7f157335f212fad0de34af75bab87e578a0b86aaf0953de7ac001cacb022b52f58329cef3eb96d383596dbc2ecb4c11b211cad30aade6a5acb2368c469dc515eb78574c04793774940a54e0a60711af10911682817cb7219e203e1a0e288c5652ac12c34a935c137a0dc4b1e73e0c47ef9d619599f76b3983a84eee8609a808ef20b315063ec39a5b16ade5ff348c04b1b9a2ad3f97e5da0170955f1fcc9dcb44d52408585bf721e760bfcb58277d2c289027ec0d58d9f32846a9593e16449bba8d06358e4d0cc455e535f722cb8b54e251e3b33f8b3a3623d5228ba2861fba56392ca26679b6620a9a3929144befe1e12df8f7c55d4385a2720caa6aec74f7e557b9a5441a5ff0cf761cba6385febf0f5f3b7ed44b18086bfea7a68e8de3711396b523966a05705fa9a32826c184315e0c7d30dce2c5a2d990ddf1a357d9f802b6748ae42c01fb8068f5361f4525be7f4f39f5790bd818672188319e4d01314a7a47e9ccb56c553c4107f9b21f0603f2bc8e9d50d4b8fa40b95891319141119c27cf79d4df7f0abc11219993c2daaf785ac3ec11f55298bcbd49fbea56691dc34fbe9713261e943824b5e714eae775e7a4133402224c7145f097108c2c18c2230efd4eeecf93bb53b03f5337f600181f606a408c76e08aa49eb5ee3505fd22ee1d16310ad7a0b504fcd2891f4d677f9af4667f6ae938cdb6dbcdbbd409f4c7efcfea2327a2c5218a114da119a0c1908f8e09caea4d9749bdecc88724552076ea9a2815df5ad60ddfeed42404e12d56eae28ebfcbcd46edaafc6f7e0f4fbffc6da0864b65dac66e7175abc1a2fa318a00182e8f7817537a2dde35460013d34a46c044fae6a114af14b4594e59734d4663d6f7ef503a9721b915b83ba1c6ec7e9d956bb40775873f32753564922fb6d50201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff5b03c8a0070499d8095a1000000000000000000000000000000000403762383934396261636638653838666265363233663738383831363937316361616237623063613362373264643363393834386366343863623266316464336400000000016d8e814a000000001976a9143fd78e0eb6a079b9c48fec1501853da057f0f56d88ac0000000002000000019d26e7633ec88160ff5130da5c8f82cd9e7eef72acff2dcd3ca9e7ff102a5a54030000006a4730440220265e70787ceb0baa7685c8090bea7c1d02a2ed1f454328f4fa02bf954ad9e54c02202ae340ed2e8abea8f29854058c7509ce9b2cb3298d575e10d2d5ad969666416c4121033e2e2eaefbe75fdec3db57ea908cc44ac49289de1216eb11ce186d94849b8581feffffff02b160a32b000000001976a914b2743e71a671da1dfbc7430981d967a0b1d3c5ac88ac83093e00000000001976a91474c7cc96920ee3a78c982ddbb06a6e780c81669488acc7a00700"
}

15
tests/blocks/bitcoingold_mainnet_80000.json

@ -0,0 +1,15 @@
{
"hash": "000000000043a8c0fd1d6f726790caa2a406010d19efd2780db27bdbbd93baf6",
"size": 373,
"height": 80000,
"merkleroot": "8fb300e3fdb6f30a4c67233b997f99fdd518b968b9a3fd65857bfe78b2600719",
"tx": [
"c06fbab289f723c6261d3030ddb6be121f7d2508d77862bb1e484f5cd7f92b25",
"5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2"
],
"time": 1284613427,
"nonce": "00000000000000000000000000000000000000000000000000000000572fe301",
"bits": "1b5bede6",
"previousblockhash": "00000000001937917bd2caba204bb1aa530ec1de9d0f6736e5d85d96da9c8bba",
"block": "01000000ba8b9cda965dd8e536670f9ddec10e53aab14b20bacad27b9137190000000000190760b278fe7b8565fda3b968b918d5fd997f993b23674c0af3b6fde300b38f000000000000000000000000000000000000000000000000000000000000000033a5914ce6ed5b1b01e32f5700000000000000000000000000000000000000000000000000000000000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704e6ed5b1b014effffffff0100f2052a01000000434104b68a50eaa0287eff855189f949c1c6e5f58b37c88231373d8a59809cbae83059cc6469d65c665ccfd1cfeb75c6e8e19413bba7fbff9bc762419a76d87b16086eac000000000100000001a6b97044d03da79c005b20ea9c0e1a6d9dc12d9f7b91a5911c9030a439eed8f5000000004948304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d1090db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501ffffffff0100f2052a010000001976a914404371705fa9bd789a2fcd52d2c580b65d35549d88ac00000000"
}
Loading…
Cancel
Save