refactor-022b.diff

This commit is contained in:
2026-01-04 10:01:37 -04:00
parent 9817546064
commit da937f2c1b
14 changed files with 2898 additions and 4135 deletions

453
heirs.py
View File

@@ -1,25 +1,39 @@
# import json
import math
# import datetime
# import urllib.request
# import urllib.parse
import random
import re
import json
from typing import Optional, Tuple, Dict, Any, TYPE_CHECKING,Sequence,List
import threading
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Tuple
import dns
import threading
import math
from dns.exception import DNSException
from electrum import bitcoin,dnssec,descriptor,constants
from electrum.util import read_json_file, write_json_file, to_string,bfh,trigger_callback
from electrum import bitcoin, constants, descriptor, dnssec
from electrum.logging import Logger, get_logger
from electrum.transaction import PartialTxInput, PartialTxOutput,TxOutpoint,PartialTransaction,TxOutput
import datetime
import urllib.request
import urllib.parse
import random
from .util import Util
from electrum.transaction import (
PartialTransaction,
PartialTxInput,
PartialTxOutput,
TxOutpoint,
TxOutput,
)
from electrum.util import (
bfh,
read_json_file,
to_string,
trigger_callback,
write_json_file,
)
from .util import *
from .willexecutors import Willexecutors
if TYPE_CHECKING:
from .wallet_db import WalletDB
from .simple_config import SimpleConfig
from .wallet_db import WalletDB
_logger = get_logger(__name__)
@@ -29,6 +43,8 @@ HEIR_AMOUNT = 1
HEIR_LOCKTIME = 2
HEIR_REAL_AMOUNT = 3
TRANSACTION_LABEL = "inheritance transaction"
class AliasNotFoundException(Exception):
pass
@@ -36,7 +52,8 @@ class AliasNotFoundException(Exception):
def reduce_outputs(in_amount, out_amount, fee, outputs):
if in_amount < out_amount:
for output in outputs:
output.value = math.floor((in_amount-fee)/out_amount * output.value)
output.value = math.floor((in_amount - fee) / out_amount * output.value)
"""
#TODO: put this method inside wallet.db to replace or complete get_locktime_for_new_transaction
@@ -61,35 +78,41 @@ def get_current_height(network:'Network'):
"""
def prepare_transactions(locktimes, available_utxos, fees, wallet):
available_utxos=sorted(available_utxos, key=lambda x:"{}:{}:{}".format(x.value_sats(),x.prevout.txid,x.prevout.out_idx))
available_utxos = sorted(
available_utxos,
key=lambda x: "{}:{}:{}".format(
x.value_sats(), x.prevout.txid, x.prevout.out_idx
),
)
total_used_utxos = []
txsout={}
locktime,_=Util.get_lowest_locktimes(locktimes)
txsout = {}
locktime, _ = get_lowest_locktimes(locktimes)
if not locktime:
return
locktime=locktime[0]
locktime = locktime[0]
heirs = locktimes[locktime]
vero=True
vero = True
while vero:
vero=False
fee=fees.get(locktime,0)
vero = False
fee = fees.get(locktime, 0)
out_amount = fee
description = ""
outputs = []
paid_heirs = {}
for name,heir in heirs.items():
for name, heir in heirs.items():
try:
if len(heir)>HEIR_REAL_AMOUNT:
if len(heir) > HEIR_REAL_AMOUNT:
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))
paid_heirs[name] = heir
outputs.append(
PartialTxOutput.from_address_and_value(
heir[HEIR_ADDRESS], real_amount
)
)
else:
pass
except Exception as e:
@@ -109,35 +132,42 @@ def prepare_transactions(locktimes, available_utxos, fees, wallet):
pass
if int(in_amount) < int(out_amount):
break
heirsvalue=out_amount
heirsvalue = out_amount
change = get_change_output(wallet, in_amount, out_amount, fee)
if change:
outputs.append(change)
for i in range(0,100):
for i in range(0, 100):
random.shuffle(outputs)
print(outputs)
tx = PartialTransaction.from_io(used_utxos, outputs, locktime=Util.parse_locktime_string(locktime,wallet), version=2)
if len(description)>0: tx.description = description[:-1]
else: tx.description = ""
tx = PartialTransaction.from_io(
used_utxos,
outputs,
locktime=parse_locktime_string(locktime, wallet),
version=2,
)
if len(description) > 0:
tx.description = description[:-1]
else:
tx.description = ""
tx.heirsvalue = heirsvalue
tx.set_rbf(True)
tx.set_rbf(True)
tx.remove_signatures()
txid = tx.txid()
if txid is None:
raise Exception("txid is none",tx)
raise Exception("txid is none", tx)
tx.heirs = paid_heirs
tx.my_locktime = locktime
txsout[txid]=tx
txsout[txid] = tx
if change:
change_idx=tx.get_output_idxs_from_address(change.address)
change_idx = tx.get_output_idxs_from_address(change.address)
prevout = TxOutpoint(txid=bfh(tx.txid()), out_idx=change_idx.pop())
txin = PartialTxInput(prevout=prevout)
txin._trusted_value_sats = change.value
txin.script_descriptor = change.script_descriptor
txin.is_mine=True
txin._TxInput__address=change.address
txin.is_mine = True
txin._TxInput__address = change.address
txin._TxInput__scriptpubkey = change.scriptpubkey
txin._TxInput__value_sats = change.value
txin.utxo = tx
@@ -146,67 +176,74 @@ def prepare_transactions(locktimes, available_utxos, fees, wallet):
return txsout
def get_utxos_from_inputs(tx_inputs,tx,utxos):
def get_utxos_from_inputs(tx_inputs, tx, utxos):
for tx_input in tx_inputs:
prevoutstr=tx_input.prevout.to_str()
utxos[prevoutstr] =utxos.get(prevoutstr,{'input':tx_input,'txs':[]})
utxos[prevoutstr]['txs'].append(tx)
prevoutstr = tx_input.prevout.to_str()
utxos[prevoutstr] = utxos.get(prevoutstr, {"input": tx_input, "txs": []})
utxos[prevoutstr]["txs"].append(tx)
return utxos
#TODO calculate de minimum inputs to be invalidated
# TODO calculate de minimum inputs to be invalidated
def invalidate_inheritance_transactions(wallet):
listids = []
utxos = {}
dtxs = {}
for k,v in wallet.get_all_labels().items():
for k, v in wallet.get_all_labels().items():
tx = None
if TRANSACTION_LABEL == v:
tx=wallet.adb.get_transaction(k)
tx = wallet.adb.get_transaction(k)
if tx:
dtxs[tx.txid()]=tx
get_utxos_from_inputs(tx.inputs(),tx,utxos)
dtxs[tx.txid()] = tx
get_utxos_from_inputs(tx.inputs(), tx, utxos)
for key,utxo in utxos.items():
txid=key.split(":")[0]
for key, utxo in utxos.items():
txid = key.split(":")[0]
if txid in dtxs:
for tx in utxo['txs']:
txid =tx.txid()
for tx in utxo["txs"]:
txid = tx.txid()
del dtxs[txid]
utxos = {}
for txid,tx in dtxs.items():
get_utxos_from_inputs(tx.inputs(),tx,utxos)
for txid, tx in dtxs.items():
get_utxos_from_inputs(tx.inputs(), tx, utxos)
utxos = sorted(utxos.items(), key = lambda item: len(item[1]))
utxos = sorted(utxos.items(), key=lambda item: len(item[1]))
remaining={}
remaining = {}
invalidated = []
for key,value in utxos:
for tx in value['txs']:
for key, value in utxos:
for tx in value["txs"]:
txid = tx.txid()
if not txid in invalidated:
invalidated.append(tx.txid())
remaining[key] = value
def print_transaction(heirs,tx,locktimes,tx_fees):
jtx=tx.to_json()
def print_transaction(heirs, tx, locktimes, tx_fees):
jtx = tx.to_json()
print(f"TX: {tx.txid()}\t-\tLocktime: {jtx['locktime']}")
print(f"---")
for inp in jtx["inputs"]:
print(f"{inp['address']}: {inp['value_sats']}")
print(f"---")
for out in jtx["outputs"]:
heirname=""
heirname = ""
for key in heirs.keys():
heir=heirs[key]
if heir[HEIR_ADDRESS] == out['address'] and str(heir[HEIR_LOCKTIME]) == str(jtx['locktime']):
heirname=key
heir = heirs[key]
if heir[HEIR_ADDRESS] == out["address"] and str(heir[HEIR_LOCKTIME]) == str(
jtx["locktime"]
):
heirname = key
print(f"{heirname}\t{out['address']}: {out['value_sats']}")
print()
size = tx.estimated_size()
print("fee: {}\texpected: {}\tsize: {}".format(tx.input_value()-tx.output_value(), size*tx_fees, size))
print(
"fee: {}\texpected: {}\tsize: {}".format(
tx.input_value() - tx.output_value(), size * tx_fees, size
)
)
print()
try:
@@ -215,30 +252,31 @@ def print_transaction(heirs,tx,locktimes,tx_fees):
print("impossible to serialize")
print()
def get_change_output(wallet,in_amount,out_amount,fee):
def get_change_output(wallet, in_amount, out_amount, fee):
change_amount = int(in_amount - out_amount - fee)
if change_amount > wallet.dust_threshold():
change_addresses = wallet.get_change_addresses_for_new_transaction()
out = PartialTxOutput.from_address_and_value(change_addresses[0], change_amount)
out.is_change = True
return out
class Heirs(dict, Logger):
def __init__(self, db: 'WalletDB'):
class Heirs(dict, Logger):
def __init__(self, db: "WalletDB"):
Logger.__init__(self)
self.db = db
d = self.db.get('heirs', {})
d = self.db.get("heirs", {})
try:
self.update(d)
except e as Exception:
return
def invalidate_transactions(self,wallet):
def invalidate_transactions(self, wallet):
invalidate_inheritance_transactions(wallet)
def save(self):
self.db.put('heirs', dict(self))
self.db.put("heirs", dict(self))
def import_file(self, path):
data = read_json_file(path)
@@ -259,25 +297,33 @@ class Heirs(dict, Logger):
self.save()
return res
def get_locktimes(self,from_locktime, a=False):
def get_locktimes(self, from_locktime, a=False):
locktimes = {}
for key in self.keys():
locktime = Util.parse_locktime_string(self[key][HEIR_LOCKTIME])
if locktime > from_locktime and not a \
or locktime <=from_locktime and a:
locktimes[int(locktime)]=None
locktime = parse_locktime_string(self[key][HEIR_LOCKTIME])
if locktime > from_locktime and not a or locktime <= from_locktime and a:
locktimes[int(locktime)] = None
return locktimes.keys()
def check_locktime(self):
return False
def normalize_perc(self, heir_list, total_balance, relative_balance,wallet,real=False):
def normalize_perc(
self, heir_list, total_balance, relative_balance, wallet, real=False
):
amount = 0
for key,v in heir_list.items():
for key, v in heir_list.items():
try:
column = HEIR_AMOUNT
if real: column = HEIR_REAL_AMOUNT
value = int(math.floor(total_balance/relative_balance*self.amount_to_float(v[column])))
if real:
column = HEIR_REAL_AMOUNT
value = int(
math.floor(
total_balance
/ relative_balance
* self.amount_to_float(v[column])
)
)
if value > wallet.dust_threshold():
heir_list[key].insert(HEIR_REAL_AMOUNT, value)
amount += value
@@ -286,7 +332,7 @@ class Heirs(dict, Logger):
raise e
return amount
def amount_to_float(self,amount):
def amount_to_float(self, amount):
try:
return float(amount)
except:
@@ -295,92 +341,114 @@ class Heirs(dict, Logger):
except:
return 0.0
def fixed_percent_lists_amount(self,from_locktime,dust_threshold,reverse = False):
def fixed_percent_lists_amount(self, from_locktime, dust_threshold, reverse=False):
fixed_heirs = {}
fixed_amount = 0.0
percent_heirs= {}
percent_heirs = {}
percent_amount = 0.0
for key in self.keys():
try:
cmp= Util.parse_locktime_string(self[key][HEIR_LOCKTIME]) - from_locktime
if cmp<=0:
cmp = parse_locktime_string(self[key][HEIR_LOCKTIME]) - from_locktime
if cmp <= 0:
continue
if Util.is_perc(self[key][HEIR_AMOUNT]):
if is_perc(self[key][HEIR_AMOUNT]):
percent_amount += float(self[key][HEIR_AMOUNT][:-1])
percent_heirs[key] =list(self[key])
percent_heirs[key] = list(self[key])
else:
heir_amount = int(math.floor(float(self[key][HEIR_AMOUNT])))
if heir_amount>dust_threshold:
if heir_amount > dust_threshold:
fixed_amount += heir_amount
fixed_heirs[key] = list(self[key])
fixed_heirs[key].insert(HEIR_REAL_AMOUNT,heir_amount)
fixed_heirs[key].insert(HEIR_REAL_AMOUNT, heir_amount)
else:
pass
except Exception as e:
except Exception as e:
_logger.error(e)
return fixed_heirs,fixed_amount,percent_heirs,percent_amount
return fixed_heirs, fixed_amount, percent_heirs, percent_amount
def prepare_lists(self, balance, total_fees, wallet, willexecutor = False, from_locktime = 0):
willexecutors_amount = 0
def prepare_lists(
self, balance, total_fees, wallet, willexecutor=False, from_locktime=0
):
willexecutors_amount = 0
willexecutors = {}
heir_list = {}
onlyfixed = False
newbalance = balance - total_fees
locktimes = self.get_locktimes(from_locktime);
locktimes = self.get_locktimes(from_locktime)
if willexecutor:
for locktime in locktimes:
if int(Util.int_locktime(locktime)) > int(from_locktime):
if int(int_locktime(locktime)) > int(from_locktime):
try:
base_fee = int(willexecutor['base_fee'])
base_fee = int(willexecutor["base_fee"])
willexecutors_amount += base_fee
h = [None] * 4
h[HEIR_AMOUNT] = base_fee
h[HEIR_REAL_AMOUNT] = base_fee
h[HEIR_LOCKTIME] = locktime
h[HEIR_ADDRESS] = willexecutor['address']
willexecutors["w!ll3x3c\""+willexecutor['url']+"\""+str(locktime)] = h
h[HEIR_ADDRESS] = willexecutor["address"]
willexecutors[
'w!ll3x3c"' + willexecutor["url"] + '"' + str(locktime)
] = h
except Exception as e:
return [],False
return [], False
else:
_logger.error(f"heir excluded from will locktime({locktime}){Util.int_locktime(locktime)}<minimum{from_locktime}"),
(
_logger.error(
f"heir excluded from will locktime({locktime}){int_locktime(locktime)}<minimum{from_locktime}"
),
)
heir_list.update(willexecutors)
newbalance -= willexecutors_amount
fixed_heirs,fixed_amount,percent_heirs,percent_amount = self.fixed_percent_lists_amount(from_locktime,wallet.dust_threshold())
fixed_heirs, fixed_amount, percent_heirs, percent_amount = (
self.fixed_percent_lists_amount(from_locktime, wallet.dust_threshold())
)
if fixed_amount > newbalance:
fixed_amount = self.normalize_perc(fixed_heirs,newbalance,fixed_amount,wallet)
fixed_amount = self.normalize_perc(
fixed_heirs, newbalance, fixed_amount, wallet
)
onlyfixed = True
heir_list.update(fixed_heirs)
newbalance -= fixed_amount
if newbalance > 0:
perc_amount = self.normalize_perc(percent_heirs,newbalance,percent_amount,wallet)
perc_amount = self.normalize_perc(
percent_heirs, newbalance, percent_amount, wallet
)
newbalance -= perc_amount
heir_list.update(percent_heirs)
if newbalance > 0:
newbalance += fixed_amount
fixed_amount = self.normalize_perc(fixed_heirs,newbalance,fixed_amount,wallet,real=True)
fixed_amount = self.normalize_perc(
fixed_heirs, newbalance, fixed_amount, wallet, real=True
)
newbalance -= fixed_amount
heir_list.update(fixed_heirs)
heir_list = sorted(heir_list.items(), key = lambda item: Util.parse_locktime_string(item[1][HEIR_LOCKTIME],wallet))
heir_list = sorted(
heir_list.items(),
key=lambda item: parse_locktime_string(item[1][HEIR_LOCKTIME], wallet),
)
locktimes = {}
for key, value in heir_list:
locktime=Util.parse_locktime_string(value[HEIR_LOCKTIME])
if not locktime in locktimes: locktimes[locktime]={key:value}
else: locktimes[locktime][key]=value
locktime = parse_locktime_string(value[HEIR_LOCKTIME])
if not locktime in locktimes:
locktimes[locktime] = {key: value}
else:
locktimes[locktime][key] = value
return locktimes, onlyfixed
def is_perc(self,key):
return Util.is_perc(self[key][HEIR_AMOUNT])
def buildTransactions(self,bal_plugin,wallet,tx_fees = None, utxos=None,from_locktime=0):
def is_perc(self, key):
return is_perc(self[key][HEIR_AMOUNT])
def buildTransactions(
self, bal_plugin, wallet, tx_fees=None, utxos=None, from_locktime=0
):
Heirs._validate(self)
if len(self)<=0:
if len(self) <= 0:
return
balance = 0.0
len_utxo_set = 0
@@ -388,20 +456,21 @@ class Heirs(dict, Logger):
if not utxos:
utxos = wallet.get_utxos()
willexecutors = Willexecutors.get_willexecutors(bal_plugin) or {}
self.decimal_point=bal_plugin.get_decimal_point()
self.decimal_point = bal_plugin.get_decimal_point()
no_willexecutors = bal_plugin.NO_WILLEXECUTOR.get()
for utxo in utxos:
if utxo.value_sats()> 0*tx_fees:
if utxo.value_sats() > 0 * tx_fees:
balance += utxo.value_sats()
len_utxo_set += 1
available_utxos.append(utxo)
if len_utxo_set==0: return
j=-2
if len_utxo_set == 0:
return
j = -2
willexecutorsitems = list(willexecutors.items())
willexecutorslen = len(willexecutorsitems)
alltxs = {}
while True:
j+=1
j += 1
if j >= willexecutorslen:
break
elif 0 <= j:
@@ -409,7 +478,7 @@ class Heirs(dict, Logger):
if not Willexecutors.is_selected(willexecutor):
continue
else:
willexecutor['url']=url
willexecutor["url"] = url
elif j == -1:
if not no_willexecutors:
continue
@@ -417,78 +486,84 @@ class Heirs(dict, Logger):
else:
break
fees = {}
i=0
i = 0
while True:
txs = {}
redo = False
i+=1
total_fees=0
i += 1
total_fees = 0
for fee in fees:
total_fees += int(fees[fee])
newbalance = balance
locktimes, onlyfixed = self.prepare_lists(balance, total_fees, wallet, willexecutor, from_locktime)
newbalance = balance
locktimes, onlyfixed = self.prepare_lists(
balance, total_fees, wallet, willexecutor, from_locktime
)
try:
txs = prepare_transactions(locktimes, available_utxos[:], fees, wallet)
txs = prepare_transactions(
locktimes, available_utxos[:], fees, wallet
)
if not txs:
return {}
except Exception as e:
try:
if "w!ll3x3c" in e.heirname:
Willexecutors.is_selected(willexecutors[w],False)
Willexecutors.is_selected(willexecutors[w], False)
break
except:
raise e
total_fees = 0
total_fees_real = 0
total_in = 0
for txid,tx in txs.items():
for txid, tx in txs.items():
tx.willexecutor = willexecutor
fee = tx.estimated_size() * tx_fees
txs[txid].tx_fees= tx_fees
fee = tx.estimated_size() * tx_fees
txs[txid].tx_fees = tx_fees
total_fees += fee
total_fees_real += tx.get_fee()
total_in += tx.input_value()
rfee= tx.input_value()-tx.output_value()
rfee = tx.input_value() - tx.output_value()
if rfee < fee or rfee > fee + wallet.dust_threshold():
redo = True
oldfees= fees.get(tx.my_locktime,0)
fees[tx.my_locktime]=fee
oldfees = fees.get(tx.my_locktime, 0)
fees[tx.my_locktime] = fee
if balance - total_in > wallet.dust_threshold():
if balance - total_in > wallet.dust_threshold():
redo = True
if not redo:
break
if i>=10:
if i >= 10:
break
alltxs.update(txs)
return alltxs
def get_transactions(self,bal_plugin,wallet,tx_fees,utxos=None,from_locktime=0):
txs=self.buildTransactions(bal_plugin,wallet,tx_fees,utxos,from_locktime)
def get_transactions(
self, bal_plugin, wallet, tx_fees, utxos=None, from_locktime=0
):
txs = self.buildTransactions(bal_plugin, wallet, tx_fees, utxos, from_locktime)
if txs:
temp_txs = {}
for txid in txs:
if txs[txid].available_utxos:
temp_txs.update(self.get_transactions(bal_plugin,wallet,tx_fees,txs[txid].available_utxos,txs[txid].locktime))
temp_txs.update(
self.get_transactions(
bal_plugin,
wallet,
tx_fees,
txs[txid].available_utxos,
txs[txid].locktime,
)
)
txs.update(temp_txs)
return txs
def resolve(self, k):
if bitcoin.is_address(k):
return {
'address': k,
'type': 'address'
}
return {"address": k, "type": "address"}
if k in self.keys():
_type, addr = self[k]
if _type == 'address':
return {
'address': addr,
'type': 'heir'
}
if _type == "address":
return {"address": addr, "type": "heir"}
if openalias := self.resolve_openalias(k):
return openalias
raise AliasNotFoundException("Invalid Bitcoin address or alias", k)
@@ -499,10 +574,10 @@ class Heirs(dict, Logger):
if out:
address, name, validated = out
return {
'address': address,
'name': name,
'type': 'openalias',
'validated': validated
"address": address,
"name": name,
"type": "openalias",
"validated": validated,
}
return {}
@@ -510,21 +585,19 @@ class Heirs(dict, Logger):
for k in self.keys():
_type, addr = self[k]
if addr.casefold() == name.casefold():
return {
'name': addr,
'type': _type,
'address': k
}
return {"name": addr, "type": _type, "address": k}
return None
def fetch_openalias(self, config: 'SimpleConfig'):
def fetch_openalias(self, config: "SimpleConfig"):
self.alias_info = None
alias = config.OPENALIAS_ID
if alias:
alias = str(alias)
def f():
self.alias_info = self._resolve_openalias(alias)
trigger_callback('alias_received')
trigger_callback("alias_received")
t = threading.Thread(target=f)
t.daemon = True
t.start()
@@ -532,18 +605,18 @@ class Heirs(dict, Logger):
@classmethod
def _resolve_openalias(cls, url: str) -> Optional[Tuple[str, str, bool]]:
# support email-style addresses, per the OA standard
url = url.replace('@', '.')
url = url.replace("@", ".")
try:
records, validated = dnssec.query(url, dns.rdatatype.TXT)
except DNSException as e:
_logger.info(f'Error resolving openalias: {repr(e)}')
_logger.info(f"Error resolving openalias: {repr(e)}")
return None
prefix = 'btc'
prefix = "btc"
for record in records:
string = to_string(record.strings[0], 'utf8')
if string.startswith('oa1:' + prefix):
address = cls.find_regex(string, r'recipient_address=([A-Za-z0-9]+)')
name = cls.find_regex(string, r'recipient_name=([^;]+)')
string = to_string(record.strings[0], "utf8")
if string.startswith("oa1:" + prefix):
address = cls.find_regex(string, r"recipient_address=([A-Za-z0-9]+)")
name = cls.find_regex(string, r"recipient_name=([^;]+)")
if not name:
name = address
if not address:
@@ -558,7 +631,6 @@ class Heirs(dict, Logger):
except AttributeError:
return None
def validate_address(address):
if not bitcoin.is_address(address):
raise NotAnAddress(f"not an address,{address}")
@@ -566,43 +638,50 @@ class Heirs(dict, Logger):
def validate_amount(amount):
try:
famount = float(amount[:-1]) if Util.is_perc(amount) else float(amount)
famount = float(amount[:-1]) if is_perc(amount) else float(amount)
if famount <= 0.00000001:
raise AmountNotValid(f"amount have to be positive {famount} < 0")
except Exception as e:
raise AmountNotValid(f"amount not properly formatted, {e}")
return amount
def validate_locktime(locktime,timestamp_to_check=False):
def validate_locktime(locktime, timestamp_to_check=False):
try:
if timestamp_to_check:
if Util.parse_locktime_string(locktime,None) < timestamp_to_check:
if parse_locktime_string(locktime, None) < timestamp_to_check:
raise HeirExpiredException()
except Exception as e:
raise LocktimeNotValid(f"locktime string not properly formatted, {e}")
return locktime
def validate_heir(k,v,timestamp_to_check=False):
def validate_heir(k, v, timestamp_to_check=False):
address = Heirs.validate_address(v[HEIR_ADDRESS])
amount = Heirs.validate_amount(v[HEIR_AMOUNT])
locktime = Heirs.validate_locktime(v[HEIR_LOCKTIME],timestamp_to_check)
return (address,amount,locktime)
locktime = Heirs.validate_locktime(v[HEIR_LOCKTIME], timestamp_to_check)
return (address, amount, locktime)
def _validate(data,timestamp_to_check=False):
def _validate(data, timestamp_to_check=False):
for k, v in list(data.items()):
if k == 'heirs':
if k == "heirs":
return Heirs._validate(v)
try:
Heirs.validate_heir(k,v)
Heirs.validate_heir(k, v)
except Exception as e:
data.pop(k)
return data
class NotAnAddress(ValueError):
pass
class AmountNotValid(ValueError):
pass
class LocktimeNotValid(ValueError):
pass
class HeirExpiredException(LocktimeNotValid):
pass