Browse Source

allow to save unbroadcasted transactions in wallet

3.1
ThomasV 7 years ago
parent
commit
e6dd3e6ad8
  1. 1
      gui/qt/history_list.py
  2. 9
      lib/commands.py
  3. 2
      lib/synchronizer.py
  4. 66
      lib/wallet.py

1
gui/qt/history_list.py

@ -37,6 +37,7 @@ TX_ICONS = [
"warning.png", "warning.png",
"unconfirmed.png", "unconfirmed.png",
"unconfirmed.png", "unconfirmed.png",
"warning.png",
"clock1.png", "clock1.png",
"clock2.png", "clock2.png",
"clock3.png", "clock3.png",

9
lib/commands.py

@ -629,6 +629,15 @@ class Commands:
out = self.wallet.get_payment_request(addr, self.config) out = self.wallet.get_payment_request(addr, self.config)
return self._format_request(out) return self._format_request(out)
@command('w')
def addtransaction(self, tx):
""" Add a transaction to the wallet history """
#fixme: we should ensure that tx is related to wallet
tx = Transaction(tx)
self.wallet.add_transaction(tx.txid(), tx)
self.wallet.save_transactions()
return tx.txid()
@command('wp') @command('wp')
def signrequest(self, address, password=None): def signrequest(self, address, password=None):
"Sign payment request with an OpenAlias" "Sign payment request with an OpenAlias"

2
lib/synchronizer.py

@ -88,7 +88,7 @@ class Synchronizer(ThreadJob):
if not params: if not params:
return return
addr = params[0] addr = params[0]
history = self.wallet.get_address_history(addr) history = self.wallet.history.get(addr, [])
if self.get_status(history) != result: if self.get_status(history) != result:
if self.requested_histories.get(addr) is None: if self.requested_histories.get(addr) is None:
self.requested_histories[addr] = result self.requested_histories[addr] = result

66
lib/wallet.py

@ -69,6 +69,7 @@ TX_STATUS = [
_('Low fee'), _('Low fee'),
_('Unconfirmed'), _('Unconfirmed'),
_('Not Verified'), _('Not Verified'),
_('Local'),
] ]
@ -404,28 +405,30 @@ class Abstract_Wallet(PrintError):
return self.network.get_local_height() if self.network else self.storage.get('stored_height', 0) return self.network.get_local_height() if self.network else self.storage.get('stored_height', 0)
def get_tx_height(self, tx_hash): def get_tx_height(self, tx_hash):
""" return the height and timestamp of a verified transaction. """ """ return the height and timestamp of a transaction. """
with self.lock: with self.lock:
if tx_hash in self.verified_tx: if tx_hash in self.verified_tx:
height, timestamp, pos = self.verified_tx[tx_hash] height, timestamp, pos = self.verified_tx[tx_hash]
conf = max(self.get_local_height() - height + 1, 0) conf = max(self.get_local_height() - height + 1, 0)
return height, conf, timestamp return height, conf, timestamp
else: elif tx_hash in self.unverified_tx:
height = self.unverified_tx[tx_hash] height = self.unverified_tx[tx_hash]
return height, 0, False return height, 0, False
else:
# local transaction
return -2, 0, False
def get_txpos(self, tx_hash): def get_txpos(self, tx_hash):
"return position, even if the tx is unverified" "return position, even if the tx is unverified"
with self.lock: with self.lock:
x = self.verified_tx.get(tx_hash) if tx_hash in self.verified_tx:
y = self.unverified_tx.get(tx_hash) height, timestamp, pos = self.verified_tx[tx_hash]
if x:
height, timestamp, pos = x
return height, pos return height, pos
elif y > 0: elif tx_hash in self.unverified_tx:
return y, 0 height = self.unverified_tx[tx_hash]
return (height, 0) if height>0 else (1e9 - height), 0
else: else:
return 1e12 - y, 0 return (1e9+1, 0)
def is_found(self): def is_found(self):
return self.history.values() != [[]] * len(self.history) return self.history.values() != [[]] * len(self.history)
@ -520,7 +523,7 @@ class Abstract_Wallet(PrintError):
status = _("%d confirmations") % conf status = _("%d confirmations") % conf
else: else:
status = _('Not verified') status = _('Not verified')
else: elif height in [-1,0]:
status = _('Unconfirmed') status = _('Unconfirmed')
if fee is None: if fee is None:
fee = self.tx_fees.get(tx_hash) fee = self.tx_fees.get(tx_hash)
@ -529,6 +532,9 @@ class Abstract_Wallet(PrintError):
fee_per_kb = fee * 1000 / size fee_per_kb = fee * 1000 / size
exp_n = self.network.config.reverse_dynfee(fee_per_kb) exp_n = self.network.config.reverse_dynfee(fee_per_kb)
can_bump = is_mine and not tx.is_final() can_bump = is_mine and not tx.is_final()
else:
status = _('Local')
can_broadcast = self.network is not None
else: else:
status = _("Signed") status = _("Signed")
can_broadcast = self.network is not None can_broadcast = self.network is not None
@ -550,7 +556,7 @@ class Abstract_Wallet(PrintError):
return tx_hash, status, label, can_broadcast, can_bump, amount, fee, height, conf, timestamp, exp_n return tx_hash, status, label, can_broadcast, can_bump, amount, fee, height, conf, timestamp, exp_n
def get_addr_io(self, address): def get_addr_io(self, address):
h = self.history.get(address, []) h = self.get_address_history(address)
received = {} received = {}
sent = {} sent = {}
for tx_hash, height in h: for tx_hash, height in h:
@ -649,9 +655,14 @@ class Abstract_Wallet(PrintError):
xx += x xx += x
return cc, uu, xx return cc, uu, xx
def get_address_history(self, address): def get_address_history(self, addr):
with self.lock: h = []
return self.history.get(address, []) with self.transaction_lock:
for tx_hash in self.transactions:
if addr in self.txi.get(tx_hash, []) or addr in self.txo.get(tx_hash, []):
tx_height = self.get_tx_height(tx_hash)[0]
h.append((tx_hash, tx_height))
return h
def find_pay_to_pubkey_address(self, prevout_hash, prevout_n): def find_pay_to_pubkey_address(self, prevout_hash, prevout_n):
dd = self.txo.get(prevout_hash, {}) dd = self.txo.get(prevout_hash, {})
@ -748,10 +759,9 @@ class Abstract_Wallet(PrintError):
old_hist = self.history.get(addr, []) old_hist = self.history.get(addr, [])
for tx_hash, height in old_hist: for tx_hash, height in old_hist:
if (tx_hash, height) not in hist: if (tx_hash, height) not in hist:
# remove tx if it's not referenced in histories # make tx local
self.tx_addr_hist[tx_hash].remove(addr) self.unverified_tx.pop(tx_hash, None)
if not self.tx_addr_hist[tx_hash]: self.verified_tx.pop(tx_hash, None)
self.remove_transaction(tx_hash)
self.history[addr] = hist self.history[addr] = hist
for tx_hash, tx_height in hist: for tx_hash, tx_height in hist:
@ -844,10 +854,12 @@ class Abstract_Wallet(PrintError):
is_lowfee = fee < low_fee * 0.5 is_lowfee = fee < low_fee * 0.5
else: else:
is_lowfee = False is_lowfee = False
if height==0 and not is_final: if height == -2:
status = 0 status = 5
elif height < 0: elif height == -1:
status = 1 status = 1
elif height==0 and not is_final:
status = 0
elif height == 0 and is_lowfee: elif height == 0 and is_lowfee:
status = 2 status = 2
elif height == 0: elif height == 0:
@ -855,9 +867,9 @@ class Abstract_Wallet(PrintError):
else: else:
status = 4 status = 4
else: else:
status = 4 + min(conf, 6) status = 5 + min(conf, 6)
time_str = format_time(timestamp) if timestamp else _("unknown") time_str = format_time(timestamp) if timestamp else _("unknown")
status_str = TX_STATUS[status] if status < 5 else time_str status_str = TX_STATUS[status] if status < 6 else time_str
return status, status_str return status, status_str
def relayfee(self): def relayfee(self):
@ -967,14 +979,6 @@ class Abstract_Wallet(PrintError):
# add it in case it was previously unconfirmed # add it in case it was previously unconfirmed
self.add_unverified_tx(tx_hash, tx_height) self.add_unverified_tx(tx_hash, tx_height)
# if we are on a pruning server, remove unverified transactions
with self.lock:
vr = list(self.verified_tx.keys()) + list(self.unverified_tx.keys())
for tx_hash in list(self.transactions):
if tx_hash not in vr:
self.print_error("removing transaction", tx_hash)
self.transactions.pop(tx_hash)
def start_threads(self, network): def start_threads(self, network):
self.network = network self.network = network
if self.network is not None: if self.network is not None:

Loading…
Cancel
Save