Browse Source

Minimum supported protocol version is 1.1

patch-2
Neil Booth 7 years ago
parent
commit
7d9ffbbed0
  1. 31
      server/controller.py
  2. 94
      server/session.py

31
server/controller.py

@ -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)

94
server/session.py

@ -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…
Cancel
Save