Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions src/electrumx/lib/coins.py
Original file line number Diff line number Diff line change
Expand Up @@ -1593,15 +1593,14 @@ class Blackcoin(ScryptMixin, Coin):
P2SH_VERBYTES = (bytes.fromhex("55"),)
GENESIS_HASH = ('000001faef25dec4fbcf906e6242621d'
'f2c183bf232f263d0ba5b101911e4563')
DESERIALIZER = lib_tx.DeserializerBlackcoin
DAEMON = daemon.FakeEstimateFeeDaemon
DESERIALIZER = lib_tx.DeserializerBlackcoinSegWit
DAEMON = daemon.BlackcoinDaemon
TX_COUNT = 10802426
TX_COUNT_HEIGHT = 3431329
TX_PER_BLOCK = 3
RPC_PORT = 15715
REORG_LIMIT = 500
ESTIMATE_FEE = 0.0001
RELAY_FEE = 0.0001
ESTIMATE_FEE = 0.001
PEERS = [
'electrum1.blackcoin.nl t10001 s10002',
'electrum2.blackcoin.nl t20001 s20002',
Expand All @@ -1617,15 +1616,14 @@ class BlackcoinTestnet(Blackcoin):
P2SH_VERBYTES = (bytes.fromhex("C4"),)
GENESIS_HASH = ('0000724595fb3b9609d441cbfb957761'
'5c292abf07d996d3edabc48de843642d')
DESERIALIZER = lib_tx.DeserializerBlackcoin
DAEMON = daemon.FakeEstimateFeeDaemon
DESERIALIZER = lib_tx.DeserializerBlackcoinSegWit
DAEMON = daemon.BlackcoinDaemon
TX_COUNT = 1401229
TX_COUNT_HEIGHT = 698611
TX_PER_BLOCK = 2
RPC_PORT = 25715
REORG_LIMIT = 500
ESTIMATE_FEE = 0.001
RELAY_FEE = 0.001
PEERS = [
'electrum1.blackcoin.nl t10011 s10012',
'electrum2.blackcoin.nl t20011 s20012',
Expand Down
80 changes: 66 additions & 14 deletions src/electrumx/lib/tx.py
Original file line number Diff line number Diff line change
Expand Up @@ -851,18 +851,73 @@ def blake2s(data):
return blake2s_hash.digest()


class DeserializerBlackcoin(Deserializer):
class DeserializerBlackcoinSegWit(DeserializerSegWit):
'''Deserializer for Blackcoin transactions.
* V1 Includes a 4-byte `nTime` field:
Returns: TxTime | TxTimeSegWit
* V2 Standard Bitcoin format (no `nTime` field):
Returns: Tx | TxSegWit
'''
BLACKCOIN_TX_VERSION = 2

def _get_version(self):
'''Peek at the transaction version without advancing the cursor.'''
result, = unpack_le_int32_from(self.binary, self.cursor)
return result

def read_tx(self):
def _read_tx_parts(self):
orig_start = self.cursor
start = self.cursor
version = self._get_version()

if version < self.BLACKCOIN_TX_VERSION:
# V1: 4-byte nTime shifts SegWit marker to offset 8.
if (self.cursor + 9 < self._binary_length and
self.binary[self.cursor + 8] == 0 and
self.binary[self.cursor + 9] != 0):
# V1 SegWit: version + time + marker + flag + ...
version = self._read_le_int32()
time = self._read_le_uint32()
start = self.cursor
orig_ser = self.binary[orig_start:start]

marker = self._read_byte()
flag = self._read_byte()

start = self.cursor
inputs = self._read_inputs()
outputs = self._read_outputs()
orig_ser += self.binary[start:self.cursor]

witness_start = self.cursor
witness = self._read_witness(len(inputs))
witness_size = self.cursor - witness_start + 2 # +2 for marker/flag

start = self.cursor
locktime = self._read_le_uint32()
orig_ser += self.binary[start:self.cursor]

base_size = self.cursor - orig_start - witness_size
weight = 4 * base_size + witness_size
vsize = weight // 4 + (weight % 4 > 0)

txid = self.TX_HASH_FN(orig_ser)
wtxid = self.TX_HASH_FN(self.binary[orig_start:self.cursor])

tx = TxTimeSegWit(
version=version,
time=time,
marker=marker,
flag=flag,
inputs=inputs,
outputs=outputs,
witness=witness,
locktime=locktime,
txid_rev=txid,
wtxid_rev=wtxid,
)
return tx, vsize

# V1 legacy: no SegWit.
tx = TxTime(
version=self._read_le_int32(),
time=self._read_le_uint32(),
Expand All @@ -872,17 +927,14 @@ def read_tx(self):
txid_rev=None,
wtxid_rev=None,
)
else:
tx = Tx(
version=self._read_le_int32(),
inputs=self._read_inputs(),
outputs=self._read_outputs(),
locktime=self._read_le_uint32(),
txid_rev=None,
wtxid_rev=None,
)
tx.txid_rev = tx.wtxid_rev = self.TX_HASH_FN(self.binary[orig_start:self.cursor])
return tx
tx.txid_rev = tx.wtxid_rev = self.TX_HASH_FN(self.binary[orig_start:self.cursor])
return tx, self.cursor - orig_start

# V2: Standard Bitcoin format (no nTime). Delegate to base class.
return super()._read_tx_parts()

def read_tx(self):
return self._read_tx_parts()[0]


class DeserializerReddcoin(Deserializer):
Expand Down
17 changes: 17 additions & 0 deletions src/electrumx/server/daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,23 @@ async def relayfee(self):
return self.coin.RELAY_FEE


class BlackcoinDaemon(Daemon):
'''Daemon for Blackcoin lacking estimatefee RPCs
and 'incrementalrelayfee' in getmempoolinfo.'''

async def estimatefee(self, block_count, estimate_mode=None):
'''Return the fee estimate for the given parameters.'''
return self.coin.ESTIMATE_FEE

async def mempool_info(self) -> dict[str, float]:
mempool_info = await self.getmempoolinfo()
return {
'mempoolminfee': mempool_info['mempoolminfee'],
'minrelaytxfee': mempool_info['minrelaytxfee'],
'incrementalrelayfee': mempool_info.get('incrementalrelayfee', 0.0),
}


class LegacyRPCDaemon(Daemon):
'''Handles connections to a daemon at the given URL.

Expand Down
26 changes: 26 additions & 0 deletions tests/blocks/blackcoin_mainnet_5962634.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"hash": "76a039c7574e10b08ce189163a1cc5e886db59fb4a40d22acc487fe4369b0977",
"confirmations": 1,
"size": 1185,
"height": 5962634,
"version": 536870912,
"versionHex": "20000000",
"merkleroot": "bc25140a8c75f2112c2560c96420a8e805760e5b31dc08ea5d4c2bb4f1e1290c",
"tx": [
"a7a15e6b2ba911fb7d2c53f6edb52d5f93d780804a69bd0b6a3de8cfd6026926",
"295ea4a96850daf5d3722d30638cc2073021c93cdb80d4ff885a8983505c8c37",
"964fa09dd6b1359654847c8990fb1bd7a71f22383d7462e34d8acb320f166906",
"b4fec47cb3ecd63699244b279f5bda4ed3188ed59be4a28ddd13c442499d7158"
],
"time": 1784719536,
"mediantime": 1784719536,
"nonce": 0,
"bits": "1a13a7fd",
"difficulty": 853519.8255535484,
"chainwork": "00000000000000000000000000000000000000000000051c364381948fd1c6cd",
"previousblockhash": "f44376a0d2fc9926eef5864685280a16850cdd2fa1f3e2838d7d14c66f53f9e6",
"flags": "proof-of-stake",
"modifier": "bc3c073b02ae1d195ae5e1aaae075cffb3bb4495a7a0f65ad44a73273c690145",
"signature": "304402202d4ee0c814a643770eab28dd78821cc08eea300fa004268a3ccb3309c1398e6402200f1d440da54a025caa16c9a2ae74dcceb192f4df914feb57c859671677702218",
"block": "00000020e6f9536fc6147d8d83e2f3a12fdd0c85160a28854686f5ee2699fcd2a07643f40c29e1f1b42b4c5dea08dc315b0e7605e8a82064c960252c11f2758c0a1425bcb0a8606afda7131a0000000004020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff06038afb5a0101ffffffff020000000000000000000000000000000000266a24aa21a9edf4789774a41c7fd39f27d3ff460e1ecad8ed86818d0d8bc2f0750f6934a7f0bb01200000000000000000000000000000000000000000000000000000000000000000000000000200000001c43fc05fe3f86d4c0bac7d0ad7de9e8d5ca3146a4c3499b0af6ddf6e46a85474010000004847304402206ee85b7c24a7a3ca4ebbb14f42ce32c01c1d78327950abbe53573101ce33d2cb0220279290999b927304c184fb2fe656485df0c65a8fc5d4574dc7fd56b1ced294ec01ffffffff03000000000000000000d4352eb111000000232103f612408b6c4bb37d491b05b565302f3ebe3f8c6cf4fd1977106daad54d77a20aacc0e1e400000000001976a914a20cf4062ecbf7358b871e6062b550aa2fb92ec788ac0000000002000000012f3fd4f94f9d0ec4cec2c3218b29257426872da284a7507e33af932a68bf8c51000000006a473044022014c90a2d5d4084f42a6f6acff358e4ce6d03ad8b411cfb4d55e01f9c06f55c2e022075356554f58ee48ba9d1c9a1d826051f882fde1effbff59b65c5b4eb655b731e0121036eabb22623e17ceaa9791500eca643e8e78e683c9540e9e05cf3ad1eb012793efdffffff024427ef47170000001976a914085f283018f571e673c38efe7a648493ce3b499088ac0000000000000000576a4c5451515350524f4f4651515032001901000000000000190076a914085f283018f571e673c38efe7a648493ce3b499088ac220060207dffe6c2f4bf3b25b966a333aa0249767a3661665efd839d7a66305d9c19eeeb00000000020000000001013717284ba41def76cccf5ac0959367c22ee0adef186f073fe9f0d70edb28d9090000000000feffffff0108c7052a01000000160014945d7a8e8655c6a3eb0433608f6f6a114e6c88040247304402203f37ba980c61eb9190f9c33ff6b0c04afa0a2e5337881418f21b2f94584ebb52022033ccac2bdff1e3934a4eba125a8cd81928370b155e62b1af03a7b6ca334cb6d3012103af816cdb5bed82c74894f7bef9e5cdb3b9476d478d5c4277b1542e3ab6272fd589fb5a0046304402202d4ee0c814a643770eab28dd78821cc08eea300fa004268a3ccb3309c1398e6402200f1d440da54a025caa16c9a2ae74dcceb192f4df914feb57c859671677702218"
}
37 changes: 37 additions & 0 deletions tests/transactions/blackcoin_mainnet_001_v2_segwit_p2wpkh.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"txid": "6c3b7453da544de05e718532abf36d752d03e64ec005eae4dfb3822697f3b321",
"hash": "36667cf3dae0e0b3d18b1f3229270b562d80c0ca7c42f59de94d0590144062be",
"version": 2,
"size": 194,
"vsize": 113,
"weight": 449,
"locktime": 5962633,
"vin": [
{
"txid": "09d928db0ed7f0e93f076f18efade02ec2679395c05acfcc76ef1da44b281737",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"txinwitness": [
"304402203f37ba980c61eb9190f9c33ff6b0c04afa0a2e5337881418f21b2f94584ebb52022033ccac2bdff1e3934a4eba125a8cd81928370b155e62b1af03a7b6ca334cb6d301",
"03af816cdb5bed82c74894f7bef9e5cdb3b9476d478d5c4277b1542e3ab6272fd5"
],
"sequence": 4294967294
}
],
"vout": [
{
"value": 4999989000,
"n": 0,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 945d7a8e8655c6a3eb0433608f6f6a114e6c8804 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a914945d7a8e8655c6a3eb0433608f6f6a114e6c880488ac",
"address": "BHyZc85obh8oLAsj4hXkAdsaWAGkYYx9GT",
"type": "pubkeyhash"
}
}
],
"hex": "020000000001013717284ba41def76cccf5ac0959367c22ee0adef186f073fe9f0d70edb28d9090000000000feffffff0108c7052a010000001976a914945d7a8e8655c6a3eb0433608f6f6a114e6c880488ac0247304402203f37ba980c61eb9190f9c33ff6b0c04afa0a2e5337881418f21b2f94584ebb52022033ccac2bdff1e3934a4eba125a8cd81928370b155e62b1af03a7b6ca334cb6d3012103af816cdb5bed82c74894f7bef9e5cdb3b9476d478d5c4277b1542e3ab6272fd589fb5a00"
}
33 changes: 33 additions & 0 deletions tests/transactions/blackcoin_mainnet_002_v2_legacy_p2pkh.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"txid": "4730aea4301091d4073a07b7eb28091c9f0dc445a3601e6b714d68a8af0da1d4",
"hash": "4730aea4301091d4073a07b7eb28091c9f0dc445a3601e6b714d68a8af0da1d4",
"version": 2,
"size": 191,
"vsize": 191,
"weight": 764,
"locktime": 0,
"vin": [
{
"txid": "9b951c2b08142a8122f916bfec2fbe634e578faef1e89ae991b83303df8bc86e",
"vout": 0,
"scriptSig": {
"asm": "304402207b7a74cd22e35925e00330eaa0f9e3aa5b3f449daba32236bb1bb742199a5c0502201e16cced25f0fce4557fe808ef23291eb85d2de81e030805b4371e5c772f69d1[ALL] 03d9c69d204e5bfa548bbf6236f12be6ddfa7b4151937210b0c78cc8e2bb34134d",
"hex": "47304402207b7a74cd22e35925e00330eaa0f9e3aa5b3f449daba32236bb1bb742199a5c0502201e16cced25f0fce4557fe808ef23291eb85d2de81e030805b4371e5c772f69d1012103d9c69d204e5bfa548bbf6236f12be6ddfa7b4151937210b0c78cc8e2bb34134d"
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 99989697000,
"n": 0,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 9a237782659d31103818426f577f1ef16bb1f9ae OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9149a237782659d31103818426f577f1ef16bb1f9ae88ac",
"address": "BJW6AY3xAveXHgeMt5NG68Bq4UNDm9UNUs",
"type": "pubkeyhash"
}
}
],
"hex": "02000000016ec88bdf0333b891e99ae8f1ae8f574e63be2fecbf16f922812a14082b1c959b000000006a47304402207b7a74cd22e35925e00330eaa0f9e3aa5b3f449daba32236bb1bb742199a5c0502201e16cced25f0fce4557fe808ef23291eb85d2de81e030805b4371e5c772f69d1012103d9c69d204e5bfa548bbf6236f12be6ddfa7b4151937210b0c78cc8e2bb34134dffffffff01e8b1d947170000001976a9149a237782659d31103818426f577f1ef16bb1f9ae88ac00000000"
}