mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-23 17:47:31 +00:00
Use attr.s for Feeupdates and Outpoints
Storage upgrade to version 23
This commit is contained in:
parent
7472eba78c
commit
aa51df0a1a
4 changed files with 72 additions and 48 deletions
|
@ -40,7 +40,7 @@ from .logging import Logger
|
||||||
|
|
||||||
OLD_SEED_VERSION = 4 # electrum versions < 2.0
|
OLD_SEED_VERSION = 4 # electrum versions < 2.0
|
||||||
NEW_SEED_VERSION = 11 # electrum versions >= 2.0
|
NEW_SEED_VERSION = 11 # electrum versions >= 2.0
|
||||||
FINAL_SEED_VERSION = 22 # electrum >= 2.7 will set this to prevent
|
FINAL_SEED_VERSION = 23 # electrum >= 2.7 will set this to prevent
|
||||||
# old versions from overwriting new format
|
# old versions from overwriting new format
|
||||||
|
|
||||||
|
|
||||||
|
@ -216,6 +216,7 @@ class JsonDB(Logger):
|
||||||
self._convert_version_20()
|
self._convert_version_20()
|
||||||
self._convert_version_21()
|
self._convert_version_21()
|
||||||
self._convert_version_22()
|
self._convert_version_22()
|
||||||
|
self._convert_version_23()
|
||||||
self.put('seed_version', FINAL_SEED_VERSION) # just to be sure
|
self.put('seed_version', FINAL_SEED_VERSION) # just to be sure
|
||||||
|
|
||||||
self._after_upgrade_tasks()
|
self._after_upgrade_tasks()
|
||||||
|
@ -515,6 +516,33 @@ class JsonDB(Logger):
|
||||||
|
|
||||||
self.put('seed_version', 22)
|
self.put('seed_version', 22)
|
||||||
|
|
||||||
|
def _convert_version_23(self):
|
||||||
|
if not self._is_upgrade_method_needed(22, 22):
|
||||||
|
return
|
||||||
|
channels = self.get('channels', [])
|
||||||
|
LOCAL = 1
|
||||||
|
REMOTE = -1
|
||||||
|
for c in channels:
|
||||||
|
# move revocation store from remote_config
|
||||||
|
r = c['remote_config'].pop('revocation_store')
|
||||||
|
c['revocation_store'] = r
|
||||||
|
# convert fee updates
|
||||||
|
log = c.get('log', {})
|
||||||
|
for sub in LOCAL, REMOTE:
|
||||||
|
l = log[str(sub)]['fee_updates']
|
||||||
|
d = {}
|
||||||
|
for i, fu in enumerate(l):
|
||||||
|
d[str(i)] = {
|
||||||
|
'rate':fu['rate'],
|
||||||
|
'ctn_local':fu['ctns'][str(LOCAL)],
|
||||||
|
'ctn_remote':fu['ctns'][str(REMOTE)]
|
||||||
|
}
|
||||||
|
log[str(int(sub))]['fee_updates'] = d
|
||||||
|
self.data['channels'] = channels
|
||||||
|
|
||||||
|
self.data['seed_version'] = 23
|
||||||
|
|
||||||
|
|
||||||
def _convert_imported(self):
|
def _convert_imported(self):
|
||||||
if not self._is_upgrade_method_needed(0, 13):
|
if not self._is_upgrade_method_needed(0, 13):
|
||||||
return
|
return
|
||||||
|
|
|
@ -752,7 +752,8 @@ class Channel(Logger):
|
||||||
other_revocation_pubkey,
|
other_revocation_pubkey,
|
||||||
derive_pubkey(this_config.delayed_basepoint.pubkey, this_point),
|
derive_pubkey(this_config.delayed_basepoint.pubkey, this_point),
|
||||||
other_config.to_self_delay,
|
other_config.to_self_delay,
|
||||||
*self.funding_outpoint,
|
self.funding_outpoint.txid,
|
||||||
|
self.funding_outpoint.output_index,
|
||||||
self.constraints.capacity,
|
self.constraints.capacity,
|
||||||
local_msat,
|
local_msat,
|
||||||
remote_msat,
|
remote_msat,
|
||||||
|
|
|
@ -14,7 +14,7 @@ class HTLCManager:
|
||||||
'locked_in': {},
|
'locked_in': {},
|
||||||
'settles': {},
|
'settles': {},
|
||||||
'fails': {},
|
'fails': {},
|
||||||
'fee_updates': [],
|
'fee_updates': {}, # "side who initiated fee update" -> action -> list of FeeUpdates
|
||||||
'revack_pending': False,
|
'revack_pending': False,
|
||||||
'next_htlc_id': 0,
|
'next_htlc_id': 0,
|
||||||
'ctn': -1, # oldest unrevoked ctx of sub
|
'ctn': -1, # oldest unrevoked ctx of sub
|
||||||
|
@ -32,7 +32,8 @@ class HTLCManager:
|
||||||
log[sub]['settles'] = {int(htlc_id): coerceHtlcOwner2IntMap(ctns) for htlc_id, ctns in log[sub]['settles'].items()}
|
log[sub]['settles'] = {int(htlc_id): coerceHtlcOwner2IntMap(ctns) for htlc_id, ctns in log[sub]['settles'].items()}
|
||||||
log[sub]['fails'] = {int(htlc_id): coerceHtlcOwner2IntMap(ctns) for htlc_id, ctns in log[sub]['fails'].items()}
|
log[sub]['fails'] = {int(htlc_id): coerceHtlcOwner2IntMap(ctns) for htlc_id, ctns in log[sub]['fails'].items()}
|
||||||
# "side who initiated fee update" -> action -> list of FeeUpdates
|
# "side who initiated fee update" -> action -> list of FeeUpdates
|
||||||
log[sub]['fee_updates'] = [FeeUpdate.from_dict(fee_upd) for fee_upd in log[sub]['fee_updates']]
|
log[sub]['fee_updates'] = { int(x): FeeUpdate(**fee_upd) for x,fee_upd in log[sub]['fee_updates'].items() }
|
||||||
|
|
||||||
if 'unacked_local_updates2' not in log:
|
if 'unacked_local_updates2' not in log:
|
||||||
log['unacked_local_updates2'] = {}
|
log['unacked_local_updates2'] = {}
|
||||||
log['unacked_local_updates2'] = {int(ctn): [bfh(msg) for msg in messages]
|
log['unacked_local_updates2'] = {int(ctn): [bfh(msg) for msg in messages]
|
||||||
|
@ -42,7 +43,7 @@ class HTLCManager:
|
||||||
assert type(initial_feerate) is int
|
assert type(initial_feerate) is int
|
||||||
for sub in (LOCAL, REMOTE):
|
for sub in (LOCAL, REMOTE):
|
||||||
if not log[sub]['fee_updates']:
|
if not log[sub]['fee_updates']:
|
||||||
log[sub]['fee_updates'].append(FeeUpdate(initial_feerate, ctns={LOCAL:0, REMOTE:0}))
|
log[sub]['fee_updates'][0] = FeeUpdate(initial_feerate, ctn_local=0, ctn_remote=0)
|
||||||
self.log = log
|
self.log = log
|
||||||
|
|
||||||
def ctn_latest(self, sub: HTLCOwner) -> int:
|
def ctn_latest(self, sub: HTLCOwner) -> int:
|
||||||
|
@ -74,7 +75,7 @@ class HTLCManager:
|
||||||
d[htlc_id] = (htlc[0], bh2u(htlc[1])) + htlc[2:]
|
d[htlc_id] = (htlc[0], bh2u(htlc[1])) + htlc[2:]
|
||||||
log[sub]['adds'] = d
|
log[sub]['adds'] = d
|
||||||
# fee_updates
|
# fee_updates
|
||||||
log[sub]['fee_updates'] = [FeeUpdate.to_dict(fee_upd) for fee_upd in log[sub]['fee_updates']]
|
log[sub]['fee_updates'] = { x:fee_upd.to_json() for x, fee_upd in self.log[sub]['fee_updates'].items() }
|
||||||
log['unacked_local_updates2'] = {ctn: [bh2u(msg) for msg in messages]
|
log['unacked_local_updates2'] = {ctn: [bh2u(msg) for msg in messages]
|
||||||
for ctn, messages in log['unacked_local_updates2'].items()}
|
for ctn, messages in log['unacked_local_updates2'].items()}
|
||||||
return log
|
return log
|
||||||
|
@ -120,22 +121,25 @@ class HTLCManager:
|
||||||
|
|
||||||
def send_update_fee(self, feerate: int) -> None:
|
def send_update_fee(self, feerate: int) -> None:
|
||||||
fee_update = FeeUpdate(rate=feerate,
|
fee_update = FeeUpdate(rate=feerate,
|
||||||
ctns={LOCAL: None, REMOTE: self.ctn_latest(REMOTE) + 1})
|
ctn_local=None, ctn_remote=self.ctn_latest(REMOTE) + 1)
|
||||||
self._new_feeupdate(fee_update, subject=LOCAL)
|
self._new_feeupdate(fee_update, subject=LOCAL)
|
||||||
|
|
||||||
def recv_update_fee(self, feerate: int) -> None:
|
def recv_update_fee(self, feerate: int) -> None:
|
||||||
fee_update = FeeUpdate(rate=feerate,
|
fee_update = FeeUpdate(rate=feerate,
|
||||||
ctns={LOCAL: self.ctn_latest(LOCAL) + 1, REMOTE: None})
|
ctn_local=self.ctn_latest(LOCAL) + 1, ctn_remote=None)
|
||||||
self._new_feeupdate(fee_update, subject=REMOTE)
|
self._new_feeupdate(fee_update, subject=REMOTE)
|
||||||
|
|
||||||
def _new_feeupdate(self, fee_update: FeeUpdate, subject: HTLCOwner) -> None:
|
def _new_feeupdate(self, fee_update: FeeUpdate, subject: HTLCOwner) -> None:
|
||||||
# overwrite last fee update if not yet committed to by anyone; otherwise append
|
# overwrite last fee update if not yet committed to by anyone; otherwise append
|
||||||
last_fee_update = self.log[subject]['fee_updates'][-1]
|
d = self.log[subject]['fee_updates']
|
||||||
if (last_fee_update.ctns[LOCAL] is None or last_fee_update.ctns[LOCAL] > self.ctn_latest(LOCAL)) \
|
assert type(d) is dict
|
||||||
and (last_fee_update.ctns[REMOTE] is None or last_fee_update.ctns[REMOTE] > self.ctn_latest(REMOTE)):
|
n = len(d)
|
||||||
self.log[subject]['fee_updates'][-1] = fee_update
|
last_fee_update = d[n-1]
|
||||||
|
if (last_fee_update.ctn_local is None or last_fee_update.ctn_local > self.ctn_latest(LOCAL)) \
|
||||||
|
and (last_fee_update.ctn_remote is None or last_fee_update.ctn_remote > self.ctn_latest(REMOTE)):
|
||||||
|
d[n-1] = fee_update
|
||||||
else:
|
else:
|
||||||
self.log[subject]['fee_updates'].append(fee_update)
|
d[n] = fee_update
|
||||||
|
|
||||||
def send_ctx(self) -> None:
|
def send_ctx(self) -> None:
|
||||||
assert self.ctn_latest(REMOTE) == self.ctn_oldest_unrevoked(REMOTE), (self.ctn_latest(REMOTE), self.ctn_oldest_unrevoked(REMOTE))
|
assert self.ctn_latest(REMOTE) == self.ctn_oldest_unrevoked(REMOTE), (self.ctn_latest(REMOTE), self.ctn_oldest_unrevoked(REMOTE))
|
||||||
|
@ -157,9 +161,9 @@ class HTLCManager:
|
||||||
if ctns[REMOTE] is None and ctns[LOCAL] <= self.ctn_latest(LOCAL):
|
if ctns[REMOTE] is None and ctns[LOCAL] <= self.ctn_latest(LOCAL):
|
||||||
ctns[REMOTE] = self.ctn_latest(REMOTE) + 1
|
ctns[REMOTE] = self.ctn_latest(REMOTE) + 1
|
||||||
# fee updates
|
# fee updates
|
||||||
for fee_update in self.log[REMOTE]['fee_updates']:
|
for k, fee_update in list(self.log[REMOTE]['fee_updates'].items()):
|
||||||
if fee_update.ctns[REMOTE] is None and fee_update.ctns[LOCAL] <= self.ctn_latest(LOCAL):
|
if fee_update.ctn_remote is None and fee_update.ctn_local <= self.ctn_latest(LOCAL):
|
||||||
fee_update.ctns[REMOTE] = self.ctn_latest(REMOTE) + 1
|
fee_update.ctn_remote = self.ctn_latest(REMOTE) + 1
|
||||||
|
|
||||||
def recv_rev(self) -> None:
|
def recv_rev(self) -> None:
|
||||||
self.log[REMOTE]['ctn'] += 1
|
self.log[REMOTE]['ctn'] += 1
|
||||||
|
@ -173,9 +177,10 @@ class HTLCManager:
|
||||||
if ctns[LOCAL] is None and ctns[REMOTE] <= self.ctn_latest(REMOTE):
|
if ctns[LOCAL] is None and ctns[REMOTE] <= self.ctn_latest(REMOTE):
|
||||||
ctns[LOCAL] = self.ctn_latest(LOCAL) + 1
|
ctns[LOCAL] = self.ctn_latest(LOCAL) + 1
|
||||||
# fee updates
|
# fee updates
|
||||||
for fee_update in self.log[LOCAL]['fee_updates']:
|
for k, fee_update in list(self.log[LOCAL]['fee_updates'].items()):
|
||||||
if fee_update.ctns[LOCAL] is None and fee_update.ctns[REMOTE] <= self.ctn_latest(REMOTE):
|
if fee_update.ctn_local is None and fee_update.ctn_remote <= self.ctn_latest(REMOTE):
|
||||||
fee_update.ctns[LOCAL] = self.ctn_latest(LOCAL) + 1
|
fee_update.ctn_local = self.ctn_latest(LOCAL) + 1
|
||||||
|
|
||||||
# no need to keep local update raw msgs anymore, they have just been ACKed.
|
# no need to keep local update raw msgs anymore, they have just been ACKed.
|
||||||
self.log['unacked_local_updates2'].pop(self.log[REMOTE]['ctn'], None)
|
self.log['unacked_local_updates2'].pop(self.log[REMOTE]['ctn'], None)
|
||||||
|
|
||||||
|
@ -198,9 +203,9 @@ class HTLCManager:
|
||||||
if ctns[LOCAL] > self.ctn_latest(LOCAL):
|
if ctns[LOCAL] > self.ctn_latest(LOCAL):
|
||||||
del self.log[LOCAL][log_action][htlc_id]
|
del self.log[LOCAL][log_action][htlc_id]
|
||||||
# fee updates
|
# fee updates
|
||||||
for i, fee_update in enumerate(list(self.log[REMOTE]['fee_updates'])):
|
for k, fee_update in list(self.log[REMOTE]['fee_updates'].items()):
|
||||||
if fee_update.ctns[LOCAL] > self.ctn_latest(LOCAL):
|
if fee_update.ctn_local > self.ctn_latest(LOCAL):
|
||||||
del self.log[REMOTE]['fee_updates'][i]
|
self.log[REMOTE]['fee_updates'].pop(k)
|
||||||
|
|
||||||
def store_local_update_raw_msg(self, raw_update_msg: bytes, *, is_commitment_signed: bool) -> None:
|
def store_local_update_raw_msg(self, raw_update_msg: bytes, *, is_commitment_signed: bool) -> None:
|
||||||
"""We need to be able to replay unacknowledged updates we sent to the remote
|
"""We need to be able to replay unacknowledged updates we sent to the remote
|
||||||
|
@ -331,7 +336,7 @@ class HTLCManager:
|
||||||
right = len(fee_log)
|
right = len(fee_log)
|
||||||
while True:
|
while True:
|
||||||
i = (left + right) // 2
|
i = (left + right) // 2
|
||||||
ctn_at_i = fee_log[i].ctns[subject]
|
ctn_at_i = fee_log[i].ctn_local if subject==LOCAL else fee_log[i].ctn_remote
|
||||||
if right - left <= 1:
|
if right - left <= 1:
|
||||||
break
|
break
|
||||||
if ctn_at_i is None: # Nones can only be on the right end
|
if ctn_at_i is None: # Nones can only be on the right end
|
||||||
|
|
|
@ -82,31 +82,17 @@ class RemoteConfig(Config):
|
||||||
next_per_commitment_point = attr.ib(type=bytes)
|
next_per_commitment_point = attr.ib(type=bytes)
|
||||||
current_per_commitment_point = attr.ib(default=None, type=bytes)
|
current_per_commitment_point = attr.ib(default=None, type=bytes)
|
||||||
|
|
||||||
#@attr.s
|
@attr.s
|
||||||
#class FeeUpdate(StoredAttr):
|
class FeeUpdate(StoredAttr):
|
||||||
# rate = attr.ib(type=int) # in sat/kw
|
rate = attr.ib(type=int) # in sat/kw
|
||||||
# ctn_local = attr.ib(default=None, type=int)
|
ctn_local = attr.ib(default=None, type=int)
|
||||||
# ctn_remote = attr.ib(default=None, type=int)
|
ctn_remote = attr.ib(default=None, type=int)
|
||||||
|
|
||||||
|
@attr.s
|
||||||
|
class ChannelConstraints(StoredAttr):
|
||||||
class FeeUpdate(NamedTuple):
|
capacity = attr.ib(type=int)
|
||||||
rate: int # in sat/kw
|
is_initiator = attr.ib(type=bool)
|
||||||
ctns: Dict['HTLCOwner', Optional[int]]
|
funding_txn_minimum_depth = attr.ib(type=int)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls, d: dict) -> 'FeeUpdate':
|
|
||||||
return FeeUpdate(rate=d['rate'],
|
|
||||||
ctns={LOCAL: d['ctns'][str(int(LOCAL))],
|
|
||||||
REMOTE: d['ctns'][str(int(REMOTE))]})
|
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
|
||||||
return {'rate': self.rate,
|
|
||||||
'ctns': {int(LOCAL): self.ctns[LOCAL],
|
|
||||||
int(REMOTE): self.ctns[REMOTE]}}
|
|
||||||
|
|
||||||
|
|
||||||
ChannelConstraints = namedtuple("ChannelConstraints", ["capacity", "is_initiator", "funding_txn_minimum_depth"])
|
|
||||||
|
|
||||||
|
|
||||||
class ScriptHtlc(NamedTuple):
|
class ScriptHtlc(NamedTuple):
|
||||||
|
@ -115,7 +101,11 @@ class ScriptHtlc(NamedTuple):
|
||||||
|
|
||||||
|
|
||||||
# FIXME duplicate of TxOutpoint in transaction.py??
|
# FIXME duplicate of TxOutpoint in transaction.py??
|
||||||
class Outpoint(NamedTuple("Outpoint", [('txid', str), ('output_index', int)])):
|
@attr.s
|
||||||
|
class Outpoint(StoredAttr):
|
||||||
|
txid = attr.ib(type=str)
|
||||||
|
output_index = attr.ib(type=int)
|
||||||
|
|
||||||
def to_str(self):
|
def to_str(self):
|
||||||
return "{}:{}".format(self.txid, self.output_index)
|
return "{}:{}".format(self.txid, self.output_index)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue