Minimum supported protocol version is 1.1
This commit is contained in:
parent
379fef17de
commit
7d9ffbbed0
@ -47,7 +47,7 @@ class Controller(ServerBase):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
CATCHING_UP, LISTENING, PAUSED, SHUTTING_DOWN = range(4)
|
CATCHING_UP, LISTENING, PAUSED, SHUTTING_DOWN = range(4)
|
||||||
PROTOCOL_MIN = '1.0'
|
PROTOCOL_MIN = '1.1'
|
||||||
PROTOCOL_MAX = '1.2'
|
PROTOCOL_MAX = '1.2'
|
||||||
VERSION = VERSION
|
VERSION = VERSION
|
||||||
|
|
||||||
@ -848,15 +848,6 @@ class Controller(ServerBase):
|
|||||||
self.assert_tx_hash(tx_hash)
|
self.assert_tx_hash(tx_hash)
|
||||||
return await self.daemon_request('getrawtransaction', tx_hash, verbose)
|
return await self.daemon_request('getrawtransaction', tx_hash, verbose)
|
||||||
|
|
||||||
async def transaction_get_1_0(self, tx_hash, height=None):
|
|
||||||
'''Return the serialized raw transaction given its hash
|
|
||||||
|
|
||||||
tx_hash: the transaction hash as a hexadecimal string
|
|
||||||
height: ignored, do not use
|
|
||||||
'''
|
|
||||||
# For some reason Electrum protocol 1.0 passes a height.
|
|
||||||
return await self.transaction_get(tx_hash)
|
|
||||||
|
|
||||||
async def transaction_get_merkle(self, tx_hash, height):
|
async def transaction_get_merkle(self, tx_hash, height):
|
||||||
'''Return the markle tree to a confirmed transaction given its hash
|
'''Return the markle tree to a confirmed transaction given its hash
|
||||||
and height.
|
and height.
|
||||||
@ -867,23 +858,3 @@ class Controller(ServerBase):
|
|||||||
self.assert_tx_hash(tx_hash)
|
self.assert_tx_hash(tx_hash)
|
||||||
height = self.non_negative_integer(height)
|
height = self.non_negative_integer(height)
|
||||||
return await self.tx_merkle(tx_hash, height)
|
return await self.tx_merkle(tx_hash, height)
|
||||||
|
|
||||||
async def utxo_get_address(self, tx_hash, index):
|
|
||||||
'''Returns the address sent to in a UTXO, or null if the UTXO
|
|
||||||
cannot be found.
|
|
||||||
|
|
||||||
tx_hash: the transaction hash of the UTXO
|
|
||||||
index: the index of the UTXO in the transaction'''
|
|
||||||
# Used only for electrum client command-line requests. We no
|
|
||||||
# longer index by address, so need to request the raw
|
|
||||||
# transaction. So it works for any TXO not just UTXOs.
|
|
||||||
self.assert_tx_hash(tx_hash)
|
|
||||||
index = self.non_negative_integer(index)
|
|
||||||
raw_tx = await self.daemon_request('getrawtransaction', tx_hash)
|
|
||||||
if not raw_tx:
|
|
||||||
return None
|
|
||||||
raw_tx = util.hex_to_bytes(raw_tx)
|
|
||||||
tx = self.coin.DESERIALIZER(raw_tx).read_tx()
|
|
||||||
if index >= len(tx.outputs):
|
|
||||||
return None
|
|
||||||
return self.coin.address_from_script(tx.outputs[index].pk_script)
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2016-2017, Neil Booth
|
# Copyright (c) 2016-2018, Neil Booth
|
||||||
#
|
#
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
@ -135,14 +135,13 @@ class ElectrumX(SessionBase):
|
|||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.subscribe_headers = False
|
self.subscribe_headers = False
|
||||||
self.subscribe_headers_raw = False
|
self.subscribe_headers_raw = False
|
||||||
self.subscribe_height = False
|
|
||||||
self.notified_height = None
|
self.notified_height = None
|
||||||
self.max_response_size = self.env.max_send
|
self.max_response_size = self.env.max_send
|
||||||
self.max_subs = self.env.max_session_subs
|
self.max_subs = self.env.max_session_subs
|
||||||
self.hashX_subs = {}
|
self.hashX_subs = {}
|
||||||
self.mempool_statuses = {}
|
self.mempool_statuses = {}
|
||||||
self.protocol_version = None
|
self.protocol_version = None
|
||||||
self.set_protocol_handlers((1, 0))
|
self.set_protocol_handlers((1, 1))
|
||||||
|
|
||||||
def sub_count(self):
|
def sub_count(self):
|
||||||
return len(self.hashX_subs)
|
return len(self.hashX_subs)
|
||||||
@ -193,9 +192,6 @@ class ElectrumX(SessionBase):
|
|||||||
if self.subscribe_headers:
|
if self.subscribe_headers:
|
||||||
args = (self.subscribe_headers_result(height), )
|
args = (self.subscribe_headers_result(height), )
|
||||||
self.send_notification('blockchain.headers.subscribe', args)
|
self.send_notification('blockchain.headers.subscribe', args)
|
||||||
if self.subscribe_height:
|
|
||||||
args = (height, )
|
|
||||||
self.send_notification('blockchain.numblocks.subscribe', args)
|
|
||||||
|
|
||||||
our_touched = touched.intersection(self.hashX_subs)
|
our_touched = touched.intersection(self.hashX_subs)
|
||||||
if our_touched or (height_changed and self.mempool_statuses):
|
if our_touched or (height_changed and self.mempool_statuses):
|
||||||
@ -227,11 +223,6 @@ class ElectrumX(SessionBase):
|
|||||||
self.notified_height = self.height()
|
self.notified_height = self.height()
|
||||||
return self.subscribe_headers_result(self.height())
|
return self.subscribe_headers_result(self.height())
|
||||||
|
|
||||||
def numblocks_subscribe(self):
|
|
||||||
'''Subscribe to get height of new blocks.'''
|
|
||||||
self.subscribe_height = True
|
|
||||||
return self.height()
|
|
||||||
|
|
||||||
async def add_peer(self, features):
|
async def add_peer(self, features):
|
||||||
'''Add a peer (but only if the peer resolves to the source).'''
|
'''Add a peer (but only if the peer resolves to the source).'''
|
||||||
peer_mgr = self.controller.peer_mgr
|
peer_mgr = self.controller.peer_mgr
|
||||||
@ -393,8 +384,7 @@ class ElectrumX(SessionBase):
|
|||||||
# that protocol version in unsupported.
|
# that protocol version in unsupported.
|
||||||
ptuple = self.controller.protocol_tuple(protocol_version)
|
ptuple = self.controller.protocol_tuple(protocol_version)
|
||||||
|
|
||||||
# From protocol version 1.1, protocol_version cannot be omitted
|
if ptuple is None:
|
||||||
if ptuple is None or (ptuple >= (1, 1) and protocol_version is None):
|
|
||||||
self.logger.info('unsupported protocol version request {}'
|
self.logger.info('unsupported protocol version request {}'
|
||||||
.format(protocol_version))
|
.format(protocol_version))
|
||||||
self.close_after_send = True
|
self.close_after_send = True
|
||||||
@ -403,11 +393,7 @@ class ElectrumX(SessionBase):
|
|||||||
|
|
||||||
self.set_protocol_handlers(ptuple)
|
self.set_protocol_handlers(ptuple)
|
||||||
|
|
||||||
# The return value depends on the protocol version
|
return (self.controller.VERSION, self.protocol_version)
|
||||||
if ptuple < (1, 1):
|
|
||||||
return self.controller.VERSION
|
|
||||||
else:
|
|
||||||
return (self.controller.VERSION, self.protocol_version)
|
|
||||||
|
|
||||||
async def transaction_broadcast(self, raw_tx):
|
async def transaction_broadcast(self, raw_tx):
|
||||||
'''Broadcast a raw transaction to the network.
|
'''Broadcast a raw transaction to the network.
|
||||||
@ -427,27 +413,6 @@ class ElectrumX(SessionBase):
|
|||||||
raise RPCError(BAD_REQUEST, 'the transaction was rejected by '
|
raise RPCError(BAD_REQUEST, 'the transaction was rejected by '
|
||||||
f'network rules.\n\n{message}\n[{raw_tx}]')
|
f'network rules.\n\n{message}\n[{raw_tx}]')
|
||||||
|
|
||||||
async def transaction_broadcast_1_0(self, raw_tx):
|
|
||||||
'''Broadcast a raw transaction to the network.
|
|
||||||
|
|
||||||
raw_tx: the raw transaction as a hexadecimal string'''
|
|
||||||
# An ugly API: current Electrum clients only pass the raw
|
|
||||||
# transaction in hex and expect error messages to be returned in
|
|
||||||
# the result field. And the server shouldn't be doing the client's
|
|
||||||
# user interface job here.
|
|
||||||
try:
|
|
||||||
return await self.transaction_broadcast(raw_tx)
|
|
||||||
except RPCError as e:
|
|
||||||
message = e.message
|
|
||||||
if 'non-mandatory-script-verify-flag' in message:
|
|
||||||
message = (
|
|
||||||
'Your client produced a transaction that is not accepted '
|
|
||||||
'by the network any more. Please upgrade to Electrum '
|
|
||||||
'2.5.1 or newer.'
|
|
||||||
)
|
|
||||||
|
|
||||||
return message
|
|
||||||
|
|
||||||
def set_protocol_handlers(self, ptuple):
|
def set_protocol_handlers(self, ptuple):
|
||||||
protocol_version = '.'.join(str(part) for part in ptuple)
|
protocol_version = '.'.join(str(part) for part in ptuple)
|
||||||
if protocol_version == self.protocol_version:
|
if protocol_version == self.protocol_version:
|
||||||
@ -466,6 +431,17 @@ class ElectrumX(SessionBase):
|
|||||||
'blockchain.estimatefee': controller.estimatefee,
|
'blockchain.estimatefee': controller.estimatefee,
|
||||||
'blockchain.headers.subscribe': self.headers_subscribe,
|
'blockchain.headers.subscribe': self.headers_subscribe,
|
||||||
'blockchain.relayfee': controller.relayfee,
|
'blockchain.relayfee': controller.relayfee,
|
||||||
|
'blockchain.scripthash.get_balance':
|
||||||
|
controller.scripthash_get_balance,
|
||||||
|
'blockchain.scripthash.get_history':
|
||||||
|
controller.scripthash_get_history,
|
||||||
|
'blockchain.scripthash.get_mempool':
|
||||||
|
controller.scripthash_get_mempool,
|
||||||
|
'blockchain.scripthash.listunspent':
|
||||||
|
controller.scripthash_listunspent,
|
||||||
|
'blockchain.scripthash.subscribe': self.scripthash_subscribe,
|
||||||
|
'blockchain.transaction.broadcast': self.transaction_broadcast,
|
||||||
|
'blockchain.transaction.get': controller.transaction_get,
|
||||||
'blockchain.transaction.get_merkle':
|
'blockchain.transaction.get_merkle':
|
||||||
controller.transaction_get_merkle,
|
controller.transaction_get_merkle,
|
||||||
'server.add_peer': self.add_peer,
|
'server.add_peer': self.add_peer,
|
||||||
@ -476,32 +452,6 @@ class ElectrumX(SessionBase):
|
|||||||
'server.version': self.server_version,
|
'server.version': self.server_version,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ptuple < (1, 1):
|
|
||||||
# Methods or semantics unique to 1.0 and earlier protocols
|
|
||||||
handlers.update({
|
|
||||||
'blockchain.numblocks.subscribe': self.numblocks_subscribe,
|
|
||||||
'blockchain.utxo.get_address': controller.utxo_get_address,
|
|
||||||
'blockchain.transaction.broadcast':
|
|
||||||
self.transaction_broadcast_1_0,
|
|
||||||
'blockchain.transaction.get': controller.transaction_get_1_0,
|
|
||||||
})
|
|
||||||
|
|
||||||
if ptuple >= (1, 1):
|
|
||||||
# New handlers as of 1.1, or different semantics
|
|
||||||
handlers.update({
|
|
||||||
'blockchain.scripthash.get_balance':
|
|
||||||
controller.scripthash_get_balance,
|
|
||||||
'blockchain.scripthash.get_history':
|
|
||||||
controller.scripthash_get_history,
|
|
||||||
'blockchain.scripthash.get_mempool':
|
|
||||||
controller.scripthash_get_mempool,
|
|
||||||
'blockchain.scripthash.listunspent':
|
|
||||||
controller.scripthash_listunspent,
|
|
||||||
'blockchain.scripthash.subscribe': self.scripthash_subscribe,
|
|
||||||
'blockchain.transaction.broadcast': self.transaction_broadcast,
|
|
||||||
'blockchain.transaction.get': controller.transaction_get,
|
|
||||||
})
|
|
||||||
|
|
||||||
if ptuple >= (1, 2):
|
if ptuple >= (1, 2):
|
||||||
# New handler as of 1.2
|
# New handler as of 1.2
|
||||||
handlers.update({
|
handlers.update({
|
||||||
@ -541,10 +491,9 @@ class DashElectrumX(ElectrumX):
|
|||||||
|
|
||||||
def set_protocol_handlers(self, ptuple):
|
def set_protocol_handlers(self, ptuple):
|
||||||
super().set_protocol_handlers(ptuple)
|
super().set_protocol_handlers(ptuple)
|
||||||
mna_broadcast = (self.masternode_announce_broadcast if ptuple >= (1, 1)
|
|
||||||
else self.masternode_announce_broadcast_1_0)
|
|
||||||
self.electrumx_handlers.update({
|
self.electrumx_handlers.update({
|
||||||
'masternode.announce.broadcast': mna_broadcast,
|
'masternode.announce.broadcast':
|
||||||
|
self.masternode_announce_broadcast,
|
||||||
'masternode.subscribe': self.masternode_subscribe,
|
'masternode.subscribe': self.masternode_subscribe,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -571,15 +520,6 @@ class DashElectrumX(ElectrumX):
|
|||||||
raise RPCError(BAD_REQUEST, 'the masternode broadcast was '
|
raise RPCError(BAD_REQUEST, 'the masternode broadcast was '
|
||||||
f'rejected.\n\n{message}\n[{signmnb}]')
|
f'rejected.\n\n{message}\n[{signmnb}]')
|
||||||
|
|
||||||
async def masternode_announce_broadcast_1_0(self, signmnb):
|
|
||||||
'''Pass through the masternode announce message to be broadcast
|
|
||||||
by the daemon.'''
|
|
||||||
# An ugly API, like the old Electrum transaction broadcast API
|
|
||||||
try:
|
|
||||||
return await self.masternode_announce_broadcast(signmnb)
|
|
||||||
except RPCError as e:
|
|
||||||
return e.message
|
|
||||||
|
|
||||||
async def masternode_subscribe(self, vin):
|
async def masternode_subscribe(self, vin):
|
||||||
'''Returns the status of masternode.'''
|
'''Returns the status of masternode.'''
|
||||||
result = await self.daemon.masternode_list(['status', vin])
|
result = await self.daemon.masternode_list(['status', vin])
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user