I couldn't find a way to query what the electrum server thinks about the blockchain through the GUI.
During the chain fork after bip66, this information was important. I was able to hack up this plugin.
'''
GET BLOCK HEADER
An electrum plugin for querying the electrum server about it's block headers
HOW TO
1. place plugin in electrum/plugins
2. start electrum on the command line
3. in the gui go Tools -> Plugins
4. enable the GetServerBlockHeaderData and press button
5. input a block height and watch the shell terminal (not electrum's console tab) for the result
example output
[{u'nonce': 697162691, u'prev_block_hash': u'00000000000000000e20bcf213a0bbd6be88d5fede6b060c737f7f8b7f1df504', u'timestamp': 1436136522, u'merkle_root': u'0fa543c7aa9f2b3b6d9755024e586c443cc1cf1cb513f9177ada9c718a1be3e6', u'block_height': 364001, u'version': 3, u'bits': 404111758}]
'''
from PyQt4 import QtCore
from PyQt4.QtGui import *
from electrum.plugins import BasePlugin, hook
from electrum.i18n import _
from electrum.wallet import Abstract_Wallet
from electrum_gui.qt.util import EnterButton
import time, traceback, threading, socket, json
class Plugin(BasePlugin):
gui = None
daemon_comm = None
def fullname(self):
return 'GetServerBlockHeaderData'
def description(self):
return _("Get block header data from the server, useful for obtaining data when the chain forks")
def requires_settings(self):
return True
def settings_widget(self, window):
return EnterButton(_('GetBlockHeader'), self.settings_dialog)
def settings_dialog(self):
print 'pressed settings'
#self.daemon_comm.send_json({'command': 'echo', 'stuff': 'here'})
d = QDialog()
d.setWindowTitle("Settings")
blockheight = QInputDialog.getText(None, 'Block Height', 'Input block height you wish to get the header of')
if not blockheight[1]:
return
blockheight = int(blockheight[0])
raw = self.gui.network.synchronous_get([ ('blockchain.block.get_header', [blockheight]) ])
print raw
#blockhash = 10
#raw = self.gui.network.synchronous_get([ ('blockchain.block.get_chunk', [blockhash]) ])
#jsonraw = str(json.loads(raw))
#print jsonraw.keys()
#if d.exec_():
# return True
#else:
# return False
@hook
def set_enabled(self, enabled):
BasePlugin.set_enabled(self, enabled)
print 'set enabled = ' + str(enabled)
'''
if enabled:
self.start_daemon_connection()
else:
self.stop_daemon_connection()
if not enabled and isinstance(self.gui.main_window.wallet, JoinMarketWallet):
print 'returning wallet to normal'
self.gui.main_window.wallet = self.gui.main_window.wallet.underlying_wallet
'''
@hook
def load_wallet(self, wallet):
print 'load wallet'
#if self.gui and self.gui.main_window.wallet and not isinstance(self.gui.main_window.wallet, JoinMarketWallet):
# print 'creating JM wallet'
# self.gui.main_window.wallet = JoinMarketWallet(self.gui.main_window.wallet, self.gui.main_window.wallet)
#in ./gui/qt/main_window.py there is broadcast_transaction()
@hook
def init_qt(self, gui):
print 'init gui'
self.gui = gui
#if self.gui.main_window.wallet and not isinstance(self.gui.main_window.wallet, JoinMarketWallet):
# print 'creating JM wallet'
# self.gui.main_window.wallet = JoinMarketWallet(self.gui.main_window.wallet, self.gui.main_window.wallet)
@hook
def make_unsigned_transaction(self, tx):
'''called when the user presses send or edits the send dialog'''
print 'make unsigned tx'
#print str(tx)
#see https://electrum.orain.org/wiki/Stratum_protocol_specification
'''
#get the address and value like this
tx_hash = '6719c7e225972bb2f935d0f923748a69868fab094fc302bbd64b7d10d89a16b0'
print 'getting txhash = ' + tx_hash
raw = self.gui.network.synchronous_get([ ('blockchain.transaction.get',[tx_hash]) ])
print str(raw)
#check its unspent and confirmed
#addr = '1JfbZRwdDHKZmuiZgYArJZhcuuzuw2HuMu'
addr = '1EtnpHTBthhXbjLn2TRfJMXu982fjPKcwM'
print 'getting addr listunspent = ' + addr
data = self.gui.network.synchronous_get([ ('blockchain.address.listunspent', [addr]) ])
print str(data)
#taker needs the following information
# info on tx being spent, unconfirmed or genuinly just in the utxo set
# the value and scriptpubkey (/ address) of such a utxo
# pushtx, should be easy
'''
if len(tx.outputs) > 2:
self.print_error('cant make coinjoins with more than one output address yet')
return
cj_addr = None
change_addr = None
cj_amount = 0
for otype, addr, value in tx.outputs:
if otype != 'address':
self.print_error('whoops, cant send to places other than addresses')
return
if self.wallet.is_change(addr):
change_addr = addr
else:
cj_addr = addr
cj_amount = value
print 'cj=' + cj_addr + ' change=' + change_addr
@hook
def sign_transaction(self, tx, password):
'''called when the user types in password after send is clicked'''
print 'sign tx ' + str(type(tx))
print str(tx)
#tx is of instance Transaction
# need to somehow find out which is the change address
address = ''
if len(address) > 0:
priv = self.wallet.get_private_key(address, password)
print 'priv = ' + str(priv)
#the tx needs enough inputs to pay the coinjoin fee, check it has enough
# if not, repeat the process in make_unsigned_transaction() to get more
# trustedcoin.py adds a fee to a tx, look how they do it
# they override Wallet class and override get_tx_fee()
# for us it might be worth overriding the function pointer
#if/when the user clicks boardcast, then send it to electrum or somehow halt the broadcast
# and send it to a maker
# need to add a hook to electrum that has the ability to halt a broadcast
# ThomasV says he would accept such a hook
# probably best is that it is able to raise an exception
@hook
def transaction_dialog(self, d):
'''called when the transaction is displayed to the user right before broadcast'''
print 'transaction dialog ' + str(type(d))
@hook
def create_send_tab(self, grid):
print 'create send tab, put coinjoin fee amount here that updates as the user types in amounts'
#self.start_daemon_connection()
#maybe get access to the address/amount field, to be able to tell between output and change
#better way would be to hook mktx() so you can see outputs
Luckily this page helped
https://electrum.orain.org/wiki/Stratum_protocol_specificationblockchain.block.get_chunk looked like a useful method too but I couldn't figure it out straight away