Preparation for moving the set of verified and unverified txs to the wallet.
The verifier will retain responsibility for verification, but will no longer hold the transaction sets itself. Change requires_fee to take a wallet. Add new function add_unverified_tx() Move get_confirmations() to the wallet from the verifier.
This commit is contained in:
parent
ffda5cd866
commit
79de458101
|
@ -813,7 +813,7 @@ class ElectrumWindow:
|
||||||
self.show_message(str(e))
|
self.show_message(str(e))
|
||||||
return
|
return
|
||||||
|
|
||||||
if tx.requires_fee(self.wallet.verifier) and fee < MIN_RELAY_TX_FEE:
|
if tx.requires_fee(self.wallet) and fee < MIN_RELAY_TX_FEE:
|
||||||
self.show_message( "This transaction requires a higher fee, or it will not be propagated by the network." )
|
self.show_message( "This transaction requires a higher fee, or it will not be propagated by the network." )
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -1200,7 +1200,7 @@ class ElectrumWindow:
|
||||||
tx = self.wallet.transactions.get(tx_hash)
|
tx = self.wallet.transactions.get(tx_hash)
|
||||||
tx.deserialize()
|
tx.deserialize()
|
||||||
is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(tx)
|
is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(tx)
|
||||||
conf, timestamp = self.wallet.verifier.get_confirmations(tx_hash)
|
conf, timestamp = self.wallet.get_confirmations(tx_hash)
|
||||||
|
|
||||||
if timestamp:
|
if timestamp:
|
||||||
time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3]
|
time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3]
|
||||||
|
|
|
@ -1121,7 +1121,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
self.show_message(str(e))
|
self.show_message(str(e))
|
||||||
return
|
return
|
||||||
|
|
||||||
if tx.get_fee() < MIN_RELAY_TX_FEE and tx.requires_fee(self.wallet.verifier):
|
if tx.get_fee() < MIN_RELAY_TX_FEE and tx.requires_fee(self.wallet):
|
||||||
QMessageBox.warning(self, _('Error'), _("This transaction requires a higher fee, or it will not be propagated by the network."), _('OK'))
|
QMessageBox.warning(self, _('Error'), _("This transaction requires a higher fee, or it will not be propagated by the network."), _('OK'))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,7 @@ class TxDialog(QDialog):
|
||||||
status = _("Signed")
|
status = _("Signed")
|
||||||
|
|
||||||
if tx_hash in self.wallet.transactions.keys():
|
if tx_hash in self.wallet.transactions.keys():
|
||||||
conf, timestamp = self.wallet.verifier.get_confirmations(tx_hash)
|
conf, timestamp = self.wallet.get_confirmations(tx_hash)
|
||||||
if timestamp:
|
if timestamp:
|
||||||
time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3]
|
time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -769,7 +769,7 @@ class Transaction:
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
def requires_fee(self, verifier):
|
def requires_fee(self, wallet):
|
||||||
# see https://en.bitcoin.it/wiki/Transaction_fees
|
# see https://en.bitcoin.it/wiki/Transaction_fees
|
||||||
#
|
#
|
||||||
# size must be smaller than 1 kbyte for free tx
|
# size must be smaller than 1 kbyte for free tx
|
||||||
|
@ -784,7 +784,7 @@ class Transaction:
|
||||||
threshold = 57600000
|
threshold = 57600000
|
||||||
weight = 0
|
weight = 0
|
||||||
for txin in self.inputs:
|
for txin in self.inputs:
|
||||||
age = verifier.get_confirmations(txin["prevout_hash"])[0]
|
age = wallet.get_confirmations(txin["prevout_hash"])[0]
|
||||||
weight += txin["value"] * age
|
weight += txin["value"] * age
|
||||||
priority = weight / size
|
priority = weight / size
|
||||||
print_error(priority, threshold)
|
print_error(priority, threshold)
|
||||||
|
|
|
@ -36,41 +36,10 @@ class SPV(util.DaemonThread):
|
||||||
self.network = network
|
self.network = network
|
||||||
self.transactions = {} # requested verifications (with height sent by the requestor)
|
self.transactions = {} # requested verifications (with height sent by the requestor)
|
||||||
self.verified_tx = storage.get('verified_tx3',{}) # height, timestamp of verified transactions
|
self.verified_tx = storage.get('verified_tx3',{}) # height, timestamp of verified transactions
|
||||||
self.merkle_roots = storage.get('merkle_roots',{}) # hashed by me
|
self.merkle_roots = {} # hashed by me
|
||||||
self.lock = threading.Lock()
|
self.lock = threading.Lock()
|
||||||
self.queue = Queue.Queue()
|
self.queue = Queue.Queue()
|
||||||
|
|
||||||
def get_confirmations(self, tx):
|
|
||||||
""" return the number of confirmations of a monitored transaction. """
|
|
||||||
with self.lock:
|
|
||||||
if tx in self.verified_tx:
|
|
||||||
height, timestamp, pos = self.verified_tx[tx]
|
|
||||||
conf = (self.network.get_local_height() - height + 1)
|
|
||||||
if conf <= 0: timestamp = None
|
|
||||||
elif tx in self.transactions:
|
|
||||||
conf = -1
|
|
||||||
timestamp = None
|
|
||||||
else:
|
|
||||||
conf = 0
|
|
||||||
timestamp = None
|
|
||||||
|
|
||||||
return conf, timestamp
|
|
||||||
|
|
||||||
|
|
||||||
def get_txpos(self, tx_hash):
|
|
||||||
"return position, even if the tx is unverified"
|
|
||||||
with self.lock:
|
|
||||||
x = self.verified_tx.get(tx_hash)
|
|
||||||
y = self.transactions.get(tx_hash)
|
|
||||||
if x:
|
|
||||||
height, timestamp, pos = x
|
|
||||||
return height, pos
|
|
||||||
elif y:
|
|
||||||
return y, 0
|
|
||||||
else:
|
|
||||||
return 1e12, 0
|
|
||||||
|
|
||||||
|
|
||||||
def get_height(self, tx_hash):
|
def get_height(self, tx_hash):
|
||||||
with self.lock:
|
with self.lock:
|
||||||
v = self.verified_tx.get(tx_hash)
|
v = self.verified_tx.get(tx_hash)
|
||||||
|
|
|
@ -387,6 +387,41 @@ class Abstract_Wallet(object):
|
||||||
decrypted = ec.decrypt_message(message)
|
decrypted = ec.decrypt_message(message)
|
||||||
return decrypted
|
return decrypted
|
||||||
|
|
||||||
|
def add_unverified_tx(self, tx_hash, tx_height):
|
||||||
|
if self.verifier and tx_height > 0:
|
||||||
|
self.verifier.add(tx_hash, tx_height)
|
||||||
|
|
||||||
|
def get_confirmations(self, tx):
|
||||||
|
""" return the number of confirmations of a monitored transaction. """
|
||||||
|
if not self.verifier:
|
||||||
|
return (None, None)
|
||||||
|
with self.verifier.lock:
|
||||||
|
if tx in self.verifier.verified_tx:
|
||||||
|
height, timestamp, pos = self.verifier.verified_tx[tx]
|
||||||
|
conf = (self.network.get_local_height() - height + 1)
|
||||||
|
if conf <= 0: timestamp = None
|
||||||
|
elif tx in self.verifier.transactions:
|
||||||
|
conf = -1
|
||||||
|
timestamp = None
|
||||||
|
else:
|
||||||
|
conf = 0
|
||||||
|
timestamp = None
|
||||||
|
|
||||||
|
return conf, timestamp
|
||||||
|
|
||||||
|
def get_txpos(self, tx_hash):
|
||||||
|
"return position, even if the tx is unverified"
|
||||||
|
with self.verifier.lock:
|
||||||
|
x = self.verifier.verified_tx.get(tx_hash)
|
||||||
|
y = self.verifier.transactions.get(tx_hash)
|
||||||
|
if x:
|
||||||
|
height, timestamp, pos = x
|
||||||
|
return height, pos
|
||||||
|
elif y:
|
||||||
|
return y, 0
|
||||||
|
else:
|
||||||
|
return 1e12, 0
|
||||||
|
|
||||||
def is_found(self):
|
def is_found(self):
|
||||||
return self.history.values() != [[]] * len(self.history)
|
return self.history.values() != [[]] * len(self.history)
|
||||||
|
|
||||||
|
@ -685,8 +720,7 @@ class Abstract_Wallet(object):
|
||||||
def receive_tx_callback(self, tx_hash, tx, tx_height):
|
def receive_tx_callback(self, tx_hash, tx, tx_height):
|
||||||
self.add_transaction(tx_hash, tx, tx_height)
|
self.add_transaction(tx_hash, tx, tx_height)
|
||||||
#self.network.pending_transactions_for_notifications.append(tx)
|
#self.network.pending_transactions_for_notifications.append(tx)
|
||||||
if self.verifier and tx_height>0:
|
self.add_unverified_tx(tx_hash, tx_height)
|
||||||
self.verifier.add(tx_hash, tx_height)
|
|
||||||
|
|
||||||
|
|
||||||
def receive_history_callback(self, addr, hist):
|
def receive_history_callback(self, addr, hist):
|
||||||
|
@ -701,10 +735,8 @@ class Abstract_Wallet(object):
|
||||||
self.storage.put('addr_history', self.history, True)
|
self.storage.put('addr_history', self.history, True)
|
||||||
|
|
||||||
for tx_hash, tx_height in hist:
|
for tx_hash, tx_height in hist:
|
||||||
if tx_height>0:
|
|
||||||
# add it in case it was previously unconfirmed
|
# add it in case it was previously unconfirmed
|
||||||
if self.verifier:
|
self.add_unverified_tx (tx_hash, tx_height)
|
||||||
self.verifier.add(tx_hash, tx_height)
|
|
||||||
|
|
||||||
# if addr is new, we have to recompute txi and txo
|
# if addr is new, we have to recompute txi and txo
|
||||||
tx = self.transactions.get(tx_hash)
|
tx = self.transactions.get(tx_hash)
|
||||||
|
@ -734,9 +766,9 @@ class Abstract_Wallet(object):
|
||||||
# 2. create sorted history
|
# 2. create sorted history
|
||||||
history = []
|
history = []
|
||||||
for tx_hash, delta in tx_deltas.items():
|
for tx_hash, delta in tx_deltas.items():
|
||||||
conf, timestamp = self.verifier.get_confirmations(tx_hash) if self.verifier else (None, None)
|
conf, timestamp = self.get_confirmations(tx_hash)
|
||||||
history.append((tx_hash, conf, delta, timestamp))
|
history.append((tx_hash, conf, delta, timestamp))
|
||||||
history.sort(key = lambda x: self.verifier.get_txpos(x[0]))
|
history.sort(key = lambda x: self.get_txpos(x[0]))
|
||||||
history.reverse()
|
history.reverse()
|
||||||
|
|
||||||
# 3. add balance
|
# 3. add balance
|
||||||
|
@ -784,7 +816,7 @@ class Abstract_Wallet(object):
|
||||||
def estimated_fee(self, tx):
|
def estimated_fee(self, tx):
|
||||||
estimated_size = len(tx.serialize(-1))/2
|
estimated_size = len(tx.serialize(-1))/2
|
||||||
fee = int(self.fee_per_kb*estimated_size/1000.)
|
fee = int(self.fee_per_kb*estimated_size/1000.)
|
||||||
if fee < MIN_RELAY_TX_FEE: # and tx.requires_fee(self.verifier):
|
if fee < MIN_RELAY_TX_FEE: # and tx.requires_fee(self):
|
||||||
fee = MIN_RELAY_TX_FEE
|
fee = MIN_RELAY_TX_FEE
|
||||||
return fee
|
return fee
|
||||||
|
|
||||||
|
@ -963,9 +995,8 @@ class Abstract_Wallet(object):
|
||||||
# review transactions that are in the history
|
# review transactions that are in the history
|
||||||
for addr, hist in self.history.items():
|
for addr, hist in self.history.items():
|
||||||
for tx_hash, tx_height in hist:
|
for tx_hash, tx_height in hist:
|
||||||
if tx_height>0:
|
|
||||||
# add it in case it was previously unconfirmed
|
# add it in case it was previously unconfirmed
|
||||||
self.verifier.add(tx_hash, tx_height)
|
self.add_unverified_tx (tx_hash, tx_height)
|
||||||
|
|
||||||
# if we are on a pruning server, remove unverified transactions
|
# if we are on a pruning server, remove unverified transactions
|
||||||
vr = self.verifier.transactions.keys() + self.verifier.verified_tx.keys()
|
vr = self.verifier.transactions.keys() + self.verifier.verified_tx.keys()
|
||||||
|
@ -1022,7 +1053,7 @@ class Abstract_Wallet(object):
|
||||||
height = item.get('height')
|
height = item.get('height')
|
||||||
if height:
|
if height:
|
||||||
print_error("found height for", tx_hash, height)
|
print_error("found height for", tx_hash, height)
|
||||||
self.verifier.add(tx_hash, height)
|
self.add_unverified_tx(tx_hash, height)
|
||||||
else:
|
else:
|
||||||
print_error("removing orphaned tx from history", tx_hash)
|
print_error("removing orphaned tx from history", tx_hash)
|
||||||
self.transactions.pop(tx_hash)
|
self.transactions.pop(tx_hash)
|
||||||
|
|
|
@ -87,7 +87,7 @@ def on_wallet_update():
|
||||||
for tx_hash, tx_height in h:
|
for tx_hash, tx_height in h:
|
||||||
tx = wallet.transactions.get(tx_hash)
|
tx = wallet.transactions.get(tx_hash)
|
||||||
if not tx: continue
|
if not tx: continue
|
||||||
if wallet.verifier.get_confirmations(tx_hash) < requested_confs: continue
|
if wallet.get_confirmations(tx_hash)[0] < requested_confs: continue
|
||||||
for o in tx.outputs:
|
for o in tx.outputs:
|
||||||
o_type, o_address, o_value = o
|
o_type, o_address, o_value = o
|
||||||
if o_address == addr:
|
if o_address == addr:
|
||||||
|
|
Loading…
Reference in New Issue