Compare commits
2 Commits
2a4eab81fd
...
609db44c1a
| Author | SHA1 | Date | |
|---|---|---|---|
|
609db44c1a
|
|||
|
0df6786f50
|
15
bal.py
15
bal.py
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
#import random
|
||||
#import zipfile as zipfile_lib
|
||||
|
||||
# import random
|
||||
# import zipfile as zipfile_lib
|
||||
|
||||
from electrum import json_db
|
||||
from electrum.logging import get_logger
|
||||
@@ -9,7 +10,7 @@ from electrum.transaction import tx_from_any
|
||||
|
||||
|
||||
def get_will_settings(x):
|
||||
#print(x)
|
||||
# print(x)
|
||||
pass
|
||||
|
||||
|
||||
@@ -18,7 +19,6 @@ json_db.register_dict("will", dict, None)
|
||||
json_db.register_dict("will_settings", lambda x: x, None)
|
||||
|
||||
|
||||
|
||||
def get_will(x):
|
||||
try:
|
||||
x["tx"] = tx_from_any(x["tx"])
|
||||
@@ -90,10 +90,10 @@ class BalPlugin(BasePlugin):
|
||||
self.PREVIEW = BalConfig(config, "bal_preview", True)
|
||||
self.SAVE_TXS = BalConfig(config, "bal_save_txs", True)
|
||||
self.WILLEXECUTORS = BalConfig(config, "bal_willexecutors", True)
|
||||
#self.PING_WILLEXECUTORS = BalConfig(config, "bal_ping_willexecutors", True)
|
||||
#self.ASK_PING_WILLEXECUTORS = BalConfig(
|
||||
# self.PING_WILLEXECUTORS = BalConfig(config, "bal_ping_willexecutors", True)
|
||||
# self.ASK_PING_WILLEXECUTORS = BalConfig(
|
||||
# config, "bal_ask_ping_willexecutors", True
|
||||
#)
|
||||
# )
|
||||
self.NO_WILLEXECUTOR = BalConfig(config, "bal_no_willexecutor", True)
|
||||
self.HIDE_REPLACED = BalConfig(config, "bal_hide_replaced", True)
|
||||
self.HIDE_INVALIDATED = BalConfig(config, "bal_hide_invalidated", True)
|
||||
@@ -149,4 +149,3 @@ class BalPlugin(BasePlugin):
|
||||
|
||||
def default_will_settings(self):
|
||||
return {"baltx_fees": 100, "threshold": "180d", "locktime": "1y"}
|
||||
|
||||
|
||||
59
heirs.py
59
heirs.py
@@ -29,6 +29,8 @@ from electrum.util import (
|
||||
|
||||
from .util import Util
|
||||
from .willexecutors import Willexecutors
|
||||
from electrum.util import BitcoinException
|
||||
from electrum import constants
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .simple_config import SimpleConfig
|
||||
@@ -41,6 +43,7 @@ HEIR_ADDRESS = 0
|
||||
HEIR_AMOUNT = 1
|
||||
HEIR_LOCKTIME = 2
|
||||
HEIR_REAL_AMOUNT = 3
|
||||
HEIR_DUST_AMOUNT = 4
|
||||
TRANSACTION_LABEL = "inheritance transaction"
|
||||
|
||||
|
||||
@@ -88,6 +91,7 @@ def prepare_transactions(locktimes, available_utxos, fees, wallet):
|
||||
txsout = {}
|
||||
locktime, _ = Util.get_lowest_locktimes(locktimes)
|
||||
if not locktime:
|
||||
_logger.info("prepare transactions, no locktime")
|
||||
return
|
||||
locktime = locktime[0]
|
||||
|
||||
@@ -101,22 +105,27 @@ def prepare_transactions(locktimes, available_utxos, fees, wallet):
|
||||
outputs = []
|
||||
paid_heirs = {}
|
||||
for name, heir in heirs.items():
|
||||
|
||||
try:
|
||||
if len(heir) > HEIR_REAL_AMOUNT:
|
||||
if len(heir) > HEIR_REAL_AMOUNT and not "DUST" in str(
|
||||
heir[HEIR_REAL_AMOUNT]
|
||||
):
|
||||
try:
|
||||
real_amount = heir[HEIR_REAL_AMOUNT]
|
||||
out_amount += real_amount
|
||||
description += f"{name}\n"
|
||||
paid_heirs[name] = heir
|
||||
outputs.append(
|
||||
PartialTxOutput.from_address_and_value(
|
||||
heir[HEIR_ADDRESS], real_amount
|
||||
)
|
||||
)
|
||||
else:
|
||||
out_amount += real_amount
|
||||
description += f"{name}\n"
|
||||
except BitcoinException as e:
|
||||
_logger.info("exception decoding output{} - {}".format(type(e), e))
|
||||
heir[HEIR_REAL_AMOUNT] = e
|
||||
|
||||
except Exception as e:
|
||||
heir[HEIR_REAL_AMOUNT] = e
|
||||
_logger.info(f"error preparing transactions {e}")
|
||||
pass
|
||||
except Exception as e:
|
||||
pass
|
||||
paid_heirs[name] = heir
|
||||
|
||||
in_amount = 0.0
|
||||
used_utxos = []
|
||||
@@ -125,12 +134,18 @@ def prepare_transactions(locktimes, available_utxos, fees, wallet):
|
||||
value = utxo.value_sats()
|
||||
in_amount += value
|
||||
used_utxos.append(utxo)
|
||||
if in_amount > out_amount:
|
||||
if in_amount >= out_amount:
|
||||
break
|
||||
|
||||
except IndexError as e:
|
||||
_logger.info(
|
||||
f"error preparing transactions index error {e} {in_amount}, {out_amount}"
|
||||
)
|
||||
pass
|
||||
if int(in_amount) < int(out_amount):
|
||||
_logger.info(
|
||||
"error preparing transactions in_amount < out_amount ({} < {}) "
|
||||
)
|
||||
break
|
||||
heirsvalue = out_amount
|
||||
change = get_change_output(wallet, in_amount, out_amount, fee)
|
||||
@@ -263,9 +278,10 @@ def get_change_output(wallet, in_amount, out_amount, fee):
|
||||
|
||||
class Heirs(dict, Logger):
|
||||
|
||||
def __init__(self, db: "WalletDB"):
|
||||
def __init__(self, wallet):
|
||||
Logger.__init__(self)
|
||||
self.db = db
|
||||
self.db = wallet.db
|
||||
self.wallet = wallet
|
||||
d = self.db.get("heirs", {})
|
||||
try:
|
||||
self.update(d)
|
||||
@@ -327,6 +343,10 @@ class Heirs(dict, Logger):
|
||||
if value > wallet.dust_threshold():
|
||||
heir_list[key].insert(HEIR_REAL_AMOUNT, value)
|
||||
amount += value
|
||||
else:
|
||||
heir_list[key].insert(HEIR_REAL_AMOUNT, f"DUST: {value}")
|
||||
heir_list[key].insert(HEIR_DUST_AMOUNT, value)
|
||||
_logger.info(f"{key}, {value} is dust will be ignored")
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
@@ -449,6 +469,7 @@ class Heirs(dict, Logger):
|
||||
):
|
||||
Heirs._validate(self)
|
||||
if len(self) <= 0:
|
||||
_logger.info("while building transactions there was no heirs")
|
||||
return
|
||||
balance = 0.0
|
||||
len_utxo_set = 0
|
||||
@@ -464,6 +485,7 @@ class Heirs(dict, Logger):
|
||||
len_utxo_set += 1
|
||||
available_utxos.append(utxo)
|
||||
if len_utxo_set == 0:
|
||||
_logger.info("no usable utxos")
|
||||
return
|
||||
j = -2
|
||||
willexecutorsitems = list(willexecutors.items())
|
||||
@@ -505,6 +527,7 @@ class Heirs(dict, Logger):
|
||||
if not txs:
|
||||
return {}
|
||||
except Exception as e:
|
||||
_logger.info(f"error preparing transactions{e}")
|
||||
try:
|
||||
if "w!ll3x3c" in e.heirname:
|
||||
Willexecutors.is_selected(willexecutors[w], False)
|
||||
@@ -632,7 +655,7 @@ class Heirs(dict, Logger):
|
||||
return None
|
||||
|
||||
def validate_address(address):
|
||||
if not bitcoin.is_address(address):
|
||||
if not bitcoin.is_address(address, net=constants.net):
|
||||
raise NotAnAddress(f"not an address,{address}")
|
||||
return address
|
||||
|
||||
@@ -661,12 +684,14 @@ class Heirs(dict, Logger):
|
||||
return (address, amount, locktime)
|
||||
|
||||
def _validate(data, timestamp_to_check=False):
|
||||
|
||||
for k, v in list(data.items()):
|
||||
if k == "heirs":
|
||||
return Heirs._validate(v)
|
||||
return Heirs._validate(v, timestamp_to_check)
|
||||
try:
|
||||
Heirs.validate_heir(k, v)
|
||||
Heirs.validate_heir(k, v, timestamp_to_check)
|
||||
except Exception as e:
|
||||
_logger.info(f"exception heir removed {e}")
|
||||
data.pop(k)
|
||||
return data
|
||||
|
||||
@@ -685,3 +710,7 @@ class LocktimeNotValid(ValueError):
|
||||
|
||||
class HeirExpiredException(LocktimeNotValid):
|
||||
pass
|
||||
|
||||
|
||||
class HeirAmountIsDustException(Exception):
|
||||
pass
|
||||
|
||||
153
qt.py
153
qt.py
@@ -145,7 +145,7 @@ from electrum.util import (
|
||||
|
||||
from .bal import BalPlugin
|
||||
from .bal_resources import DEFAULT_ICON, icon_path
|
||||
from .heirs import Heirs
|
||||
from .heirs import Heirs, HEIR_REAL_AMOUNT, HEIR_DUST_AMOUNT
|
||||
from .util import Util
|
||||
from .will import (
|
||||
AmountException,
|
||||
@@ -295,8 +295,8 @@ class Plugin(BalPlugin, Logger):
|
||||
lbl_logo = QLabel()
|
||||
lbl_logo.setPixmap(qicon)
|
||||
|
||||
#heir_ping_willexecutors = bal_checkbox(self.PING_WILLEXECUTORS)
|
||||
#heir_ask_ping_willexecutors = bal_checkbox(self.ASK_PING_WILLEXECUTORS)
|
||||
# heir_ping_willexecutors = bal_checkbox(self.PING_WILLEXECUTORS)
|
||||
# heir_ask_ping_willexecutors = bal_checkbox(self.ASK_PING_WILLEXECUTORS)
|
||||
heir_no_willexecutor = bal_checkbox(self.NO_WILLEXECUTOR)
|
||||
|
||||
def on_multiverse_change():
|
||||
@@ -327,27 +327,27 @@ class Plugin(BalPlugin, Logger):
|
||||
2,
|
||||
"Hide invalidated transactions from will detail and list",
|
||||
)
|
||||
#add_widget(
|
||||
# add_widget(
|
||||
# grid,
|
||||
# "Ping Willexecutors",
|
||||
# heir_ping_willexecutors,
|
||||
# 3,
|
||||
# "Ping willexecutors to get payment info before compiling will",
|
||||
#)
|
||||
#add_widget(
|
||||
# )
|
||||
# add_widget(
|
||||
# grid,
|
||||
# " - Ask before",
|
||||
# heir_ask_ping_willexecutors,
|
||||
# 4,
|
||||
# "Ask before to ping willexecutor",
|
||||
#)
|
||||
#add_widget(
|
||||
# )
|
||||
# add_widget(
|
||||
# grid,
|
||||
# "Backup Transaction",
|
||||
# heir_no_willexecutor,
|
||||
# 5,
|
||||
# "Add transactions without willexecutor",
|
||||
#)
|
||||
# )
|
||||
# add_widget(grid,"Enable Multiverse(EXPERIMENTAL/BROKEN)",heir_enable_multiverse,6,"enable multiple locktimes, will import.... ")
|
||||
grid.addWidget(heir_repush, 7, 0)
|
||||
grid.addWidget(
|
||||
@@ -473,7 +473,7 @@ class BalWindow(Logger):
|
||||
self.bal_plugin, update=False, bal_window=self
|
||||
)
|
||||
if not self.heirs:
|
||||
self.heirs = Heirs._validate(Heirs(self.wallet.db))
|
||||
self.heirs = Heirs._validate(Heirs(self.wallet))
|
||||
if not self.will:
|
||||
self.will = self.wallet.db.get_dict("will")
|
||||
Util.fix_will_tx_fees(self.will)
|
||||
@@ -522,7 +522,6 @@ class BalWindow(Logger):
|
||||
tab.is_shown_cv = shown_cv(True)
|
||||
return tab
|
||||
|
||||
|
||||
def new_heir_dialog(self, heir_key=None):
|
||||
heir = self.heirs.get(heir_key)
|
||||
title = "New heir"
|
||||
@@ -655,6 +654,7 @@ class BalWindow(Logger):
|
||||
Will.normalize_will(self.willitems, self.wallet)
|
||||
|
||||
def build_will(self, ignore_duplicate=True, keep_original=True):
|
||||
_logger.debug("building will...")
|
||||
will = {}
|
||||
willtodelete = []
|
||||
willtoappend = {}
|
||||
@@ -670,6 +670,7 @@ class BalWindow(Logger):
|
||||
if Willexecutors.is_selected(w):
|
||||
f = True
|
||||
if not f:
|
||||
_logger.error("No Will-Executor or backup transaction selected")
|
||||
raise NoWillExecutorNotPresent(
|
||||
"No Will-Executor or backup transaction selected"
|
||||
)
|
||||
@@ -680,7 +681,8 @@ class BalWindow(Logger):
|
||||
None,
|
||||
self.date_to_check,
|
||||
)
|
||||
self.logger.info(txs)
|
||||
|
||||
self.logger.info(f"txs built: {txs}")
|
||||
creation_time = time.time()
|
||||
if txs:
|
||||
for txid in txs:
|
||||
@@ -699,7 +701,13 @@ class BalWindow(Logger):
|
||||
tx["txchildren"] = []
|
||||
will[txid] = WillItem(tx, _id=txid, wallet=self.wallet)
|
||||
self.update_will(will)
|
||||
else:
|
||||
self.logger.info("No transactions was built")
|
||||
self.logger.info(f"will-settings: {self.will_settings}")
|
||||
self.logger.info(f"date_to_check:{self.date_to_check}")
|
||||
self.logger.info(f"heirs: {self.heirs}")
|
||||
except Exception as e:
|
||||
self.logger.info(f"Exception build_will: {e}")
|
||||
raise e
|
||||
pass
|
||||
return self.willitems
|
||||
@@ -1177,7 +1185,7 @@ class BalWindow(Logger):
|
||||
parent = self
|
||||
|
||||
def on_success(result):
|
||||
#del self.waiting_dialog
|
||||
# del self.waiting_dialog
|
||||
try:
|
||||
parent.willexecutor_list.update()
|
||||
except Exception as e:
|
||||
@@ -1757,7 +1765,9 @@ class BalWizardWEDownloadWidget(BalWizardWidget):
|
||||
|
||||
def on_success(willexecutors):
|
||||
self.bal_window.willexecutors.update(willexecutors)
|
||||
self.bal_window.ping_willexecutors(self.bal_window.willexecutors,False)
|
||||
self.bal_window.ping_willexecutors(
|
||||
self.bal_window.willexecutors, False
|
||||
)
|
||||
if index < 1:
|
||||
for we in self.bal_window.willexecutors:
|
||||
if self.bal_window.willexecutors[we]["status"] == 200:
|
||||
@@ -1828,7 +1838,6 @@ class BalWizardLocktimeAndFeeWidget(BalWizardWidget):
|
||||
self.heir_locktime.get_locktime()
|
||||
if self.heir_locktime.get_locktime()
|
||||
else "1y"
|
||||
|
||||
)
|
||||
self.bal_window.bal_plugin.WILL_SETTINGS.set(self.bal_window.will_settings)
|
||||
|
||||
@@ -1846,7 +1855,6 @@ class BalWizardLocktimeAndFeeWidget(BalWizardWidget):
|
||||
)
|
||||
self.bal_window.bal_plugin.WILL_SETTINGS.set(self.bal_window.will_settings)
|
||||
|
||||
|
||||
self.heir_threshold.valueEdited.connect(on_heir_threshold)
|
||||
|
||||
self.heir_tx_fees = QSpinBox(widget)
|
||||
@@ -2029,7 +2037,7 @@ class BalBuildWillDialog(BalDialog):
|
||||
if not parent:
|
||||
parent = bal_window.window
|
||||
BalDialog.__init__(self, parent, bal_window.bal_plugin, "Building Will")
|
||||
self.parent=parent
|
||||
self.parent = parent
|
||||
self.updatemessage.connect(self.update)
|
||||
self.bal_window = bal_window
|
||||
self.message_label = QLabel("Building Will:")
|
||||
@@ -2080,7 +2088,7 @@ class BalBuildWillDialog(BalDialog):
|
||||
self.bal_window.window.wallet.dust_threshold(),
|
||||
)
|
||||
_logger.debug("variables ok")
|
||||
self.msg_set_status("checking variables:", varrow,"Ok")
|
||||
self.msg_set_status("checking variables:", varrow, "Ok")
|
||||
except AmountException:
|
||||
self.msg_set_status(
|
||||
"checking variables",
|
||||
@@ -2093,7 +2101,7 @@ class BalBuildWillDialog(BalDialog):
|
||||
)
|
||||
+ "</font>",
|
||||
)
|
||||
|
||||
|
||||
self.msg_set_checking()
|
||||
have_to_build = False
|
||||
try:
|
||||
@@ -2110,7 +2118,7 @@ class BalBuildWillDialog(BalDialog):
|
||||
_logger.debug("no heirs")
|
||||
self.msg_set_checking("No Heirs")
|
||||
except NotCompleteWillException as e:
|
||||
_logger.debug("not complete", e)
|
||||
_logger.debug(f"not complete {e} true")
|
||||
message = False
|
||||
have_to_build = True
|
||||
if isinstance(e, HeirChangeException):
|
||||
@@ -2124,7 +2132,7 @@ class BalBuildWillDialog(BalDialog):
|
||||
elif isinstance(e, HeirNotFoundException):
|
||||
message = "Heir not found"
|
||||
if message:
|
||||
_logger.debug("message")
|
||||
_logger.debug(f"message: {message}")
|
||||
self.msg_set_checking(message)
|
||||
else:
|
||||
self.msg_set_checking("New")
|
||||
@@ -2140,6 +2148,18 @@ class BalBuildWillDialog(BalDialog):
|
||||
except Exception as e:
|
||||
self.msg_set_building(self.msg_error(e))
|
||||
return False, None
|
||||
|
||||
excluded_heirs = []
|
||||
for wid in Will.only_valid(self.bal_window.willitems):
|
||||
heirs = self.bal_window.willitems[wid].heirs
|
||||
for hid, heir in heirs.items():
|
||||
if "DUST" in str(heir[HEIR_REAL_AMOUNT]):
|
||||
self.msg_set_status(
|
||||
f'<font color="red">{hid},{heir[HEIR_DUST_AMOUNT]} is DUST',
|
||||
None,
|
||||
f"Excluded from will {wid}</font>",
|
||||
)
|
||||
|
||||
have_to_sign = False
|
||||
for wid in Will.only_valid(self.bal_window.willitems):
|
||||
if not self.bal_window.willitems[wid].get_status("COMPLETE"):
|
||||
@@ -2240,7 +2260,7 @@ class BalBuildWillDialog(BalDialog):
|
||||
if not self._stopping:
|
||||
self.loop_push()
|
||||
|
||||
def invalidate_task(self,password,bal_window,tx):
|
||||
def invalidate_task(self, password, bal_window, tx):
|
||||
_logger.debug(f"invalidate tx: {tx}")
|
||||
fee_per_byte = bal_window.will_settings.get("baltx_fees", 1)
|
||||
tx = self.bal_window.wallet.sign_transaction(tx, password)
|
||||
@@ -2269,6 +2289,7 @@ class BalBuildWillDialog(BalDialog):
|
||||
def on_error(self, error):
|
||||
_logger.error(error)
|
||||
pass
|
||||
|
||||
def on_success_phase1(self, result):
|
||||
self.have_to_sign, tx = list(result)
|
||||
_logger.debug("have to sign {}".format(self.have_to_sign))
|
||||
@@ -2287,7 +2308,7 @@ class BalBuildWillDialog(BalDialog):
|
||||
self.close()
|
||||
return
|
||||
self.thread.add(
|
||||
partial(self.invalidate_task,password,self.bal_window,tx),
|
||||
partial(self.invalidate_task, password, self.bal_window, tx),
|
||||
on_success=self.on_success_invalidate,
|
||||
on_done=self.on_accept,
|
||||
on_error=self.on_error,
|
||||
@@ -2399,8 +2420,6 @@ class BalBuildWillDialog(BalDialog):
|
||||
self.password = self.bal_window.get_wallet_password(msg, parent=self)
|
||||
|
||||
def msg_edit_row(self, line, row=None):
|
||||
_logger.debug(f"{row},{line}")
|
||||
|
||||
try:
|
||||
self.labels[row] = line
|
||||
except Exception:
|
||||
@@ -2573,9 +2592,15 @@ class HeirList(MyTreeView, MessageBoxMixin):
|
||||
items[self.Columns.NAME].setEditable(True)
|
||||
items[self.Columns.ADDRESS].setEditable(True)
|
||||
items[self.Columns.AMOUNT].setEditable(True)
|
||||
items[self.Columns.NAME].setData(key, self.ROLE_HEIR_KEY + self.Columns.NAME)
|
||||
items[self.Columns.ADDRESS].setData(key, self.ROLE_HEIR_KEY + self.Columns.ADDRESS)
|
||||
items[self.Columns.AMOUNT].setData(key, self.ROLE_HEIR_KEY + self.Columns.AMOUNT)
|
||||
items[self.Columns.NAME].setData(
|
||||
key, self.ROLE_HEIR_KEY + self.Columns.NAME
|
||||
)
|
||||
items[self.Columns.ADDRESS].setData(
|
||||
key, self.ROLE_HEIR_KEY + self.Columns.ADDRESS
|
||||
)
|
||||
items[self.Columns.AMOUNT].setData(
|
||||
key, self.ROLE_HEIR_KEY + self.Columns.AMOUNT
|
||||
)
|
||||
|
||||
row_count = self.model().rowCount()
|
||||
self.model().insertRow(row_count, items)
|
||||
@@ -2594,10 +2619,9 @@ class HeirList(MyTreeView, MessageBoxMixin):
|
||||
pass
|
||||
|
||||
def get_edit_key_from_coordinate(self, row, col):
|
||||
a= self.get_role_data_from_coordinate(
|
||||
row, col, role=self.ROLE_HEIR_KEY + col
|
||||
)
|
||||
a = self.get_role_data_from_coordinate(row, col, role=self.ROLE_HEIR_KEY + col)
|
||||
return a
|
||||
|
||||
def create_toolbar(self, config):
|
||||
toolbar, menu = self.create_toolbar_with_menu("")
|
||||
menu.addAction(_("&New Heir"), self.bal_window.new_heir_dialog)
|
||||
@@ -2605,6 +2629,7 @@ class HeirList(MyTreeView, MessageBoxMixin):
|
||||
menu.addAction(_("Export"), lambda: self.bal_window.export_heirs())
|
||||
|
||||
self.heir_locktime = HeirsLockTimeEdit(self, 0)
|
||||
|
||||
def on_heir_locktime():
|
||||
if not self.heir_locktime.get_locktime():
|
||||
self.heir_locktime.set_locktime("1y")
|
||||
@@ -2695,7 +2720,6 @@ class HeirList(MyTreeView, MessageBoxMixin):
|
||||
self.heir_threshold.set_locktime(self.bal_window.will_settings["threshold"])
|
||||
self.heir_tx_fees.setValue(int(self.bal_window.will_settings["baltx_fees"]))
|
||||
|
||||
|
||||
except Exception as e:
|
||||
_logger.debug(f"Exception update_will_settings {e}")
|
||||
|
||||
@@ -2963,16 +2987,22 @@ class PreviewList(MyTreeView):
|
||||
|
||||
def check(self):
|
||||
Will.add_willtree(self.bal_window.willitems)
|
||||
all_utxos =self.bal_window.wallet.get_utxos()
|
||||
all_utxos = self.bal_window.wallet.get_utxos()
|
||||
utxos_list = Will.utxos_strs(all_utxos)
|
||||
Will.check_invalidated(self.bal_window.willitems,utxos_list,self.bal_window.wallet)
|
||||
|
||||
Will.check_invalidated(
|
||||
self.bal_window.willitems, utxos_list, self.bal_window.wallet
|
||||
)
|
||||
|
||||
close_window = BalBuildWillDialog(self.bal_window)
|
||||
close_window.build_will_task()
|
||||
|
||||
will = {}
|
||||
for wid, w in self.bal_window.willitems.items():
|
||||
if w.get_status("VALID") and w.get_status("PUSHED") and not w.get_status("CHECKED"):
|
||||
if (
|
||||
w.get_status("VALID")
|
||||
and w.get_status("PUSHED")
|
||||
and not w.get_status("CHECKED")
|
||||
):
|
||||
will[wid] = w
|
||||
if will:
|
||||
self.bal_window.check_transactions(will)
|
||||
@@ -3008,7 +3038,7 @@ class PreviewDialog(BalDialog, MessageBoxMixin):
|
||||
self.setMinimumSize(1000, 200)
|
||||
self.size_label = QLabel()
|
||||
self.transactions_list = PreviewList(self.bal_window, self.will)
|
||||
|
||||
|
||||
self.bal_window.init_class_variables()
|
||||
self.check_will()
|
||||
|
||||
@@ -3290,7 +3320,7 @@ class WillExecutorList(MyTreeView):
|
||||
self.Columns.INFO,
|
||||
],
|
||||
)
|
||||
self.parent=parent
|
||||
self.parent = parent
|
||||
try:
|
||||
self.setModel(QStandardItemModel(self))
|
||||
self.sortByColumn(self.Columns.SELECTED, Qt.SortOrder.AscendingOrder)
|
||||
@@ -3356,9 +3386,9 @@ class WillExecutorList(MyTreeView):
|
||||
self.update()
|
||||
|
||||
def get_edit_key_from_coordinate(self, row, col):
|
||||
role=self.ROLE_HEIR_KEY+col
|
||||
role = self.ROLE_HEIR_KEY + col
|
||||
a = self.get_role_data_from_coordinate(row, col, role=role)
|
||||
return a
|
||||
return a
|
||||
|
||||
def delete(self, selected_keys):
|
||||
for key in selected_keys:
|
||||
@@ -3416,16 +3446,33 @@ class WillExecutorList(MyTreeView):
|
||||
labels[self.Columns.URL] = url
|
||||
if Willexecutors.is_selected(value):
|
||||
|
||||
labels[self.Columns.SELECTED] = [read_QIcon_from_bytes(self.parent.bal_plugin.read_file("icons/confirmed.png")),""]
|
||||
labels[self.Columns.SELECTED] = [
|
||||
read_QIcon_from_bytes(
|
||||
self.parent.bal_plugin.read_file("icons/confirmed.png")
|
||||
),
|
||||
"",
|
||||
]
|
||||
else:
|
||||
labels[self.Columns.SELECTED] = ""
|
||||
labels[self.Columns.BASE_FEE] = Util.decode_amount(
|
||||
value.get("base_fee", 0), self.get_decimal_point()
|
||||
)
|
||||
if str(value.get("status", 0)) == "200":
|
||||
labels[self.Columns.STATUS] = [read_QIcon_from_bytes(self.parent.bal_plugin.read_file("icons/status_connected.png")),""]
|
||||
labels[self.Columns.STATUS] = [
|
||||
read_QIcon_from_bytes(
|
||||
self.parent.bal_plugin.read_file(
|
||||
"icons/status_connected.png"
|
||||
)
|
||||
),
|
||||
"",
|
||||
]
|
||||
else:
|
||||
labels[self.Columns.STATUS] = [read_QIcon_from_bytes(self.parent.bal_plugin.read_file("icons/unconfirmed.png")),""]
|
||||
labels[self.Columns.STATUS] = [
|
||||
read_QIcon_from_bytes(
|
||||
self.parent.bal_plugin.read_file("icons/unconfirmed.png")
|
||||
),
|
||||
"",
|
||||
]
|
||||
labels[self.Columns.ADDRESS] = str(value.get("address", ""))
|
||||
labels[self.Columns.INFO] = str(value.get("info", ""))
|
||||
|
||||
@@ -3445,10 +3492,18 @@ class WillExecutorList(MyTreeView):
|
||||
items[self.Columns.BASE_FEE].setEditable(True)
|
||||
items[self.Columns.STATUS].setEditable(False)
|
||||
|
||||
items[self.Columns.URL].setData(url, self.ROLE_HEIR_KEY + self.Columns.URL)
|
||||
items[self.Columns.BASE_FEE].setData(url, self.ROLE_HEIR_KEY + self.Columns.BASE_FEE)
|
||||
items[self.Columns.INFO].setData(url, self.ROLE_HEIR_KEY + self.Columns.INFO)
|
||||
items[self.Columns.ADDRESS].setData(url, self.ROLE_HEIR_KEY + self.Columns.ADDRESS)
|
||||
items[self.Columns.URL].setData(
|
||||
url, self.ROLE_HEIR_KEY + self.Columns.URL
|
||||
)
|
||||
items[self.Columns.BASE_FEE].setData(
|
||||
url, self.ROLE_HEIR_KEY + self.Columns.BASE_FEE
|
||||
)
|
||||
items[self.Columns.INFO].setData(
|
||||
url, self.ROLE_HEIR_KEY + self.Columns.INFO
|
||||
)
|
||||
items[self.Columns.ADDRESS].setData(
|
||||
url, self.ROLE_HEIR_KEY + self.Columns.ADDRESS
|
||||
)
|
||||
row_count = self.model().rowCount()
|
||||
self.model().insertRow(row_count, items)
|
||||
if url == current_key:
|
||||
@@ -3516,7 +3571,7 @@ class WillExecutorWidget(QWidget, MessageBoxMixin):
|
||||
buttonbox.addWidget(b)
|
||||
|
||||
vbox.addLayout(buttonbox)
|
||||
#self.willexecutor_list.update()
|
||||
# self.willexecutor_list.update()
|
||||
|
||||
def add(self):
|
||||
self.willexecutors_list["http://localhost:8080"] = {
|
||||
@@ -3548,7 +3603,7 @@ class WillExecutorWidget(QWidget, MessageBoxMixin):
|
||||
|
||||
def update_willexecutors(self, wes=None):
|
||||
if not wes:
|
||||
wes=self.willexecutors_list
|
||||
wes = self.willexecutors_list
|
||||
self.bal_window.ping_willexecutors(wes, self.parent)
|
||||
self.willexecutors_list.update(wes)
|
||||
self.willexecutor_list.update()
|
||||
|
||||
67
will.py
67
will.py
@@ -28,7 +28,6 @@ _logger = get_logger(__name__)
|
||||
|
||||
|
||||
class Will:
|
||||
# return an array with the list of children
|
||||
def get_children(will, willid):
|
||||
out = []
|
||||
for _id in will:
|
||||
@@ -153,6 +152,16 @@ class Will:
|
||||
inp._TxInput__value_sats = change.value
|
||||
return inp
|
||||
|
||||
"""
|
||||
in questa situazione sono presenti due transazioni con id differente(quindi transazioni differenti)
|
||||
per prima cosa controllo il locktime
|
||||
se il locktime della nuova transazione e' maggiore del locktime della vecchia transazione, allora
|
||||
confronto gli eredi, per locktime se corrispondono controllo i willexecutor
|
||||
se hanno la stessa url ma le fee vecchie sono superiori alle fee nuove, allora anticipare.
|
||||
|
||||
|
||||
"""
|
||||
|
||||
def check_anticipate(ow: "WillItem", nw: "WillItem"):
|
||||
anticipate = Util.anticipate_locktime(ow.tx.locktime, days=1)
|
||||
if int(nw.tx.locktime) >= int(anticipate):
|
||||
@@ -256,7 +265,7 @@ class Will:
|
||||
to_append = {}
|
||||
new_inputs = Will.get_all_inputs(will, only_valid=True)
|
||||
for nid, nwi in will.items():
|
||||
if nwi.search_anticipate(new_inputs) or nwi.search_anticipate(old_inputs):
|
||||
if nwi.search_anticipate(new_inputs):
|
||||
if nid != nwi.tx.txid():
|
||||
redo = True
|
||||
to_delete.append(nid)
|
||||
@@ -266,6 +275,17 @@ class Will:
|
||||
Will.change_input(
|
||||
will, nid, i, outputs[i], new_inputs, to_delete, to_append
|
||||
)
|
||||
if nwi.search_anticipate(old_inputs):
|
||||
if nid != nwi.tx.txid():
|
||||
redo = True
|
||||
|
||||
to_delete.append(nid)
|
||||
to_append[nwi.tx.txid()] = nwi
|
||||
outputs = nwi.tx.outputs()
|
||||
for i in range(0, len(outputs)):
|
||||
Will.change_input(
|
||||
will, nid, i, outputs[i], new_inputs, to_delete, to_append
|
||||
)
|
||||
|
||||
for w in to_delete:
|
||||
try:
|
||||
@@ -275,6 +295,7 @@ class Will:
|
||||
for k, w in to_append.items():
|
||||
will[k] = w
|
||||
if redo:
|
||||
|
||||
Will.search_anticipate_rec(will, old_inputs)
|
||||
|
||||
def update_will(old_will, new_will):
|
||||
@@ -284,7 +305,6 @@ class Will:
|
||||
# check if the new input is already spent by other transaction
|
||||
# if it is use the same locktime, or anticipate.
|
||||
Will.search_anticipate_rec(new_will, all_old_inputs)
|
||||
|
||||
other_inputs = Will.get_all_inputs(old_will, {})
|
||||
try:
|
||||
Will.normalize_will(new_will, others_inputs=other_inputs)
|
||||
@@ -419,20 +439,22 @@ class Will:
|
||||
# check if transactions are stil valid tecnically valid
|
||||
def check_invalidated(willtree, utxos_list, wallet):
|
||||
for wid, w in willtree.items():
|
||||
#if not w.father:
|
||||
for inp in w.tx.inputs():
|
||||
inp_str = Util.utxo_to_str(inp)
|
||||
if not inp_str in utxos_list:
|
||||
if wallet:
|
||||
height = Will.check_tx_height(w.tx, wallet)
|
||||
if height < 0:
|
||||
Will.set_invalidate(wid, willtree)
|
||||
elif height == 0:
|
||||
w.set_status("PENDING", True)
|
||||
else:
|
||||
w.set_status("CONFIRMED", True)
|
||||
#else:
|
||||
# print("father",w.father)
|
||||
if (
|
||||
not w.father
|
||||
or willtree[w.father].get_status("CONFIRMED")
|
||||
or willtree[w.father].get_status("PENDING")
|
||||
):
|
||||
for inp in w.tx.inputs():
|
||||
inp_str = Util.utxo_to_str(inp)
|
||||
if not inp_str in utxos_list:
|
||||
if wallet:
|
||||
height = Will.check_tx_height(w.tx, wallet)
|
||||
if height < 0:
|
||||
Will.set_invalidate(wid, willtree)
|
||||
elif height == 0:
|
||||
w.set_status("PENDING", True)
|
||||
else:
|
||||
w.set_status("CONFIRMED", True)
|
||||
|
||||
def reflect_to_children(treeitem):
|
||||
if not treeitem.get_status("VALID"):
|
||||
@@ -632,7 +654,6 @@ class Will:
|
||||
|
||||
|
||||
class WillItem(Logger):
|
||||
|
||||
STATUS_DEFAULT = {
|
||||
"ANTICIPATED": ["Anticipated", False],
|
||||
"BROADCASTED": ["Broadcasted", False],
|
||||
@@ -654,15 +675,15 @@ class WillItem(Logger):
|
||||
}
|
||||
|
||||
def set_status(self, status, value=True):
|
||||
#_logger.trace(
|
||||
# _logger.trace(
|
||||
# "set status {} - {} {} -> {}".format(
|
||||
# self._id, status, self.STATUS[status][1], value
|
||||
# )
|
||||
#)
|
||||
# )
|
||||
if self.STATUS[status][1] == bool(value):
|
||||
return None
|
||||
|
||||
self.status += "." + ("NOT " if not value else "" + _(self.STATUS[status][0]))
|
||||
self.status += "." + (("NOT " if not value else "") + _(self.STATUS[status][0]))
|
||||
self.STATUS[status][1] = bool(value)
|
||||
if value:
|
||||
if status in ["INVALIDATED", "REPLACED", "CONFIRMED", "PENDING"]:
|
||||
@@ -867,3 +888,7 @@ class PercAmountException(AmountException):
|
||||
|
||||
class FixedAmountException(AmountException):
|
||||
pass
|
||||
|
||||
|
||||
def test_check_invalidated():
|
||||
Will.check_invalidated(will, utxos_list, wallet)
|
||||
|
||||
@@ -35,14 +35,16 @@ class Willexecutors:
|
||||
continue
|
||||
Willexecutors.initialize_willexecutor(willexecutors[w], w)
|
||||
for w in to_del:
|
||||
_logger.error("error Willexecutor to delete type:{} ", type(willexecutor[w]),w)
|
||||
_logger.error(
|
||||
"error Willexecutor to delete type:{} ", type(willexecutor[w]), w
|
||||
)
|
||||
del willexecutors[w]
|
||||
bal = bal_plugin.WILLEXECUTORS.default.get(constants.net.NET_NAME, {})
|
||||
for bal_url, bal_executor in bal.items():
|
||||
if not bal_url in willexecutors:
|
||||
_logger.debug(f"force add {bal_url} willexecutor")
|
||||
willexecutors[bal_url] = bal_executor
|
||||
#if update:
|
||||
# if update:
|
||||
# found = False
|
||||
# for url, we in willexecutors.items():
|
||||
# if Willexecutors.is_selected(we):
|
||||
@@ -119,7 +121,7 @@ class Willexecutors:
|
||||
def send_request(method, url, data=None, *, timeout=10):
|
||||
network = Network.get_instance()
|
||||
if not network:
|
||||
raise ErrorConnectingServer("You are offline.")
|
||||
raise Exception("You are offline.")
|
||||
_logger.debug(f"<-- {method} {url} {data}")
|
||||
headers = {}
|
||||
headers["user-agent"] = f"BalPlugin v:{BalPlugin.version()}"
|
||||
@@ -171,7 +173,7 @@ class Willexecutors:
|
||||
out = True
|
||||
try:
|
||||
|
||||
_logger.debug(f"willexecutor['txs']")
|
||||
_logger.debug(f"{willexecutor[url]}: {willexecutor['txs']}")
|
||||
if w := Willexecutors.send_request(
|
||||
"post",
|
||||
willexecutor["url"] + "/" + constants.net.NET_NAME + "/pushtxs",
|
||||
|
||||
Reference in New Issue
Block a user