Replace sqlalchemy with manbearpigSQL

This commit is contained in:
tecnovert 2024-11-19 21:45:19 +02:00
parent 0bd626d659
commit 757f8f2762
15 changed files with 2182 additions and 2155 deletions

View file

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-2024 tecnovert # Copyright (c) 2019-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -18,6 +19,9 @@ import subprocess
from sockshandler import SocksiPyHandler from sockshandler import SocksiPyHandler
from .db import (
DBMethods,
)
from .rpc import ( from .rpc import (
callrpc, callrpc,
) )
@ -34,7 +38,7 @@ def getaddrinfo_tor(*args):
return [(socket.AF_INET, socket.SOCK_STREAM, 6, "", (args[0], args[1]))] return [(socket.AF_INET, socket.SOCK_STREAM, 6, "", (args[0], args[1]))]
class BaseApp: class BaseApp(DBMethods):
def __init__(self, fp, data_dir, settings, chain, log_name="BasicSwap"): def __init__(self, fp, data_dir, settings, chain, log_name="BasicSwap"):
self.log_name = log_name self.log_name = log_name
self.fp = fp self.fp = fp

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,29 +1,28 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2022-2024 tecnovert # Copyright (c) 2022-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import json import json
import time import time
from sqlalchemy.sql import text
from sqlalchemy.orm import scoped_session
from .db import ( from .db import (
AutomationStrategy,
BidState, BidState,
Concepts, Concepts,
AutomationStrategy,
CURRENT_DB_VERSION,
CURRENT_DB_DATA_VERSION, CURRENT_DB_DATA_VERSION,
CURRENT_DB_VERSION,
) )
from .basicswap_util import ( from .basicswap_util import (
BidStates, BidStates,
strBidState,
isActiveBidState, isActiveBidState,
isErrorBidState, isErrorBidState,
isFailingBidState, isFailingBidState,
isFinalBidState, isFinalBidState,
strBidState,
) )
@ -36,110 +35,110 @@ def upgradeDatabaseData(self, data_version):
data_version, data_version,
CURRENT_DB_DATA_VERSION, CURRENT_DB_DATA_VERSION,
) )
with self.mxDB: cursor = self.openDB()
try: try:
session = scoped_session(self.session_factory) now = int(time.time())
now = int(time.time()) if data_version < 1:
self.add(
if data_version < 1: AutomationStrategy(
session.add( active_ind=1,
AutomationStrategy( label="Accept All",
active_ind=1, type_ind=Concepts.OFFER,
label="Accept All", data=json.dumps(
type_ind=Concepts.OFFER, {"exact_rate_only": True, "max_concurrent_bids": 5}
data=json.dumps( ).encode("utf-8"),
{"exact_rate_only": True, "max_concurrent_bids": 5} only_known_identities=False,
).encode("utf-8"), created_at=now,
only_known_identities=False, ),
created_at=now, cursor,
)
)
session.add(
AutomationStrategy(
active_ind=1,
label="Accept Known",
type_ind=Concepts.OFFER,
data=json.dumps(
{"exact_rate_only": True, "max_concurrent_bids": 5}
).encode("utf-8"),
only_known_identities=True,
note="Accept bids from identities with previously successful swaps only",
created_at=now,
)
)
for state in BidStates:
session.add(
BidState(
active_ind=1,
state_id=int(state),
in_progress=isActiveBidState(state),
in_error=isErrorBidState(state),
swap_failed=isFailingBidState(state),
swap_ended=isFinalBidState(state),
label=strBidState(state),
created_at=now,
)
)
if data_version > 0 and data_version < 2:
for state in (
BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_TX_SIGS,
BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX,
):
session.add(
BidState(
active_ind=1,
state_id=int(state),
in_progress=isActiveBidState(state),
label=strBidState(state),
created_at=now,
)
)
if data_version > 0 and data_version < 3:
for state in BidStates:
in_error = isErrorBidState(state)
swap_failed = isFailingBidState(state)
swap_ended = isFinalBidState(state)
session.execute(
text(
"UPDATE bidstates SET in_error = :in_error, swap_failed = :swap_failed, swap_ended = :swap_ended WHERE state_id = :state_id",
{
"in_error": in_error,
"swap_failed": swap_failed,
"swap_ended": swap_ended,
"state_id": int(state),
},
)
)
if data_version > 0 and data_version < 4:
for state in (
BidStates.BID_REQUEST_SENT,
BidStates.BID_REQUEST_ACCEPTED,
):
session.add(
BidState(
active_ind=1,
state_id=int(state),
in_progress=isActiveBidState(state),
in_error=isErrorBidState(state),
swap_failed=isFailingBidState(state),
swap_ended=isFinalBidState(state),
label=strBidState(state),
created_at=now,
)
)
self.db_data_version = CURRENT_DB_DATA_VERSION
self.setIntKV("db_data_version", self.db_data_version, session)
session.commit()
self.log.info(
"Upgraded database records to version {}".format(self.db_data_version)
) )
finally: self.add(
session.close() AutomationStrategy(
session.remove() active_ind=1,
label="Accept Known",
type_ind=Concepts.OFFER,
data=json.dumps(
{"exact_rate_only": True, "max_concurrent_bids": 5}
).encode("utf-8"),
only_known_identities=True,
note="Accept bids from identities with previously successful swaps only",
created_at=now,
),
cursor,
)
for state in BidStates:
self.add(
BidState(
active_ind=1,
state_id=int(state),
in_progress=isActiveBidState(state),
in_error=isErrorBidState(state),
swap_failed=isFailingBidState(state),
swap_ended=isFinalBidState(state),
label=strBidState(state),
created_at=now,
),
cursor,
)
if data_version > 0 and data_version < 2:
for state in (
BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_TX_SIGS,
BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX,
):
self.add(
BidState(
active_ind=1,
state_id=int(state),
in_progress=isActiveBidState(state),
label=strBidState(state),
created_at=now,
),
cursor,
)
if data_version > 0 and data_version < 3:
for state in BidStates:
in_error = isErrorBidState(state)
swap_failed = isFailingBidState(state)
swap_ended = isFinalBidState(state)
cursor.execute(
"UPDATE bidstates SET in_error = :in_error, swap_failed = :swap_failed, swap_ended = :swap_ended WHERE state_id = :state_id",
{
"in_error": in_error,
"swap_failed": swap_failed,
"swap_ended": swap_ended,
"state_id": int(state),
},
)
if data_version > 0 and data_version < 4:
for state in (
BidStates.BID_REQUEST_SENT,
BidStates.BID_REQUEST_ACCEPTED,
):
self.add(
BidState(
active_ind=1,
state_id=int(state),
in_progress=isActiveBidState(state),
in_error=isErrorBidState(state),
swap_failed=isFailingBidState(state),
swap_ended=isFinalBidState(state),
label=strBidState(state),
created_at=now,
),
cursor,
)
self.db_data_version = CURRENT_DB_DATA_VERSION
self.setIntKV("db_data_version", self.db_data_version, cursor)
self.commitDB()
self.log.info(
"Upgraded database records to version {}".format(self.db_data_version)
)
finally:
self.closeDB(cursor, commit=False)
def upgradeDatabase(self, db_version): def upgradeDatabase(self, db_version):
@ -147,312 +146,276 @@ def upgradeDatabase(self, db_version):
return return
self.log.info( self.log.info(
"Upgrading database from version %d to %d.", db_version, CURRENT_DB_VERSION f"Upgrading database from version {db_version} to {CURRENT_DB_VERSION}."
) )
while True: while True:
session = scoped_session(self.session_factory) try:
cursor = self.openDB()
current_version = db_version current_version = db_version
if current_version == 6: if current_version == 6:
session.execute(text("ALTER TABLE bids ADD COLUMN security_token BLOB")) cursor.execute("ALTER TABLE bids ADD COLUMN security_token BLOB")
session.execute(text("ALTER TABLE offers ADD COLUMN security_token BLOB")) cursor.execute("ALTER TABLE offers ADD COLUMN security_token BLOB")
db_version += 1 db_version += 1
elif current_version == 7: elif current_version == 7:
session.execute(text("ALTER TABLE transactions ADD COLUMN block_hash BLOB")) cursor.execute("ALTER TABLE transactions ADD COLUMN block_hash BLOB")
session.execute( cursor.execute(
text("ALTER TABLE transactions ADD COLUMN block_height INTEGER") "ALTER TABLE transactions ADD COLUMN block_height INTEGER"
)
session.execute(
text("ALTER TABLE transactions ADD COLUMN block_time INTEGER")
)
db_version += 1
elif current_version == 8:
session.execute(
text(
"""
CREATE TABLE wallets (
record_id INTEGER NOT NULL,
coin_id INTEGER,
wallet_name VARCHAR,
wallet_data VARCHAR,
balance_type INTEGER,
created_at BIGINT,
PRIMARY KEY (record_id))"""
) )
) cursor.execute("ALTER TABLE transactions ADD COLUMN block_time INTEGER")
db_version += 1 db_version += 1
elif current_version == 9: elif current_version == 8:
session.execute(text("ALTER TABLE wallets ADD COLUMN wallet_data VARCHAR")) cursor.execute(
db_version += 1
elif current_version == 10:
session.execute(
text("ALTER TABLE smsgaddresses ADD COLUMN active_ind INTEGER")
)
session.execute(
text("ALTER TABLE smsgaddresses ADD COLUMN created_at INTEGER")
)
session.execute(text("ALTER TABLE smsgaddresses ADD COLUMN note VARCHAR"))
session.execute(text("ALTER TABLE smsgaddresses ADD COLUMN pubkey VARCHAR"))
session.execute(
text("UPDATE smsgaddresses SET active_ind = 1, created_at = 1")
)
session.execute(text("ALTER TABLE offers ADD COLUMN addr_to VARCHAR"))
session.execute(text(f'UPDATE offers SET addr_to = "{self.network_addr}"'))
db_version += 1
elif current_version == 11:
session.execute(
text("ALTER TABLE bids ADD COLUMN chain_a_height_start INTEGER")
)
session.execute(
text("ALTER TABLE bids ADD COLUMN chain_b_height_start INTEGER")
)
session.execute(
text("ALTER TABLE bids ADD COLUMN protocol_version INTEGER")
)
session.execute(
text("ALTER TABLE offers ADD COLUMN protocol_version INTEGER")
)
session.execute(text("ALTER TABLE transactions ADD COLUMN tx_data BLOB"))
db_version += 1
elif current_version == 12:
session.execute(
text(
""" """
CREATE TABLE knownidentities ( CREATE TABLE wallets (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
address VARCHAR, coin_id INTEGER,
label VARCHAR, wallet_name VARCHAR,
publickey BLOB, wallet_data VARCHAR,
num_sent_bids_successful INTEGER, balance_type INTEGER,
num_recv_bids_successful INTEGER, created_at BIGINT,
num_sent_bids_rejected INTEGER, PRIMARY KEY (record_id))"""
num_recv_bids_rejected INTEGER,
num_sent_bids_failed INTEGER,
num_recv_bids_failed INTEGER,
note VARCHAR,
updated_at BIGINT,
created_at BIGINT,
PRIMARY KEY (record_id))"""
) )
) db_version += 1
session.execute(text("ALTER TABLE bids ADD COLUMN reject_code INTEGER")) elif current_version == 9:
session.execute(text("ALTER TABLE bids ADD COLUMN rate INTEGER")) cursor.execute("ALTER TABLE wallets ADD COLUMN wallet_data VARCHAR")
session.execute( db_version += 1
text("ALTER TABLE offers ADD COLUMN amount_negotiable INTEGER") elif current_version == 10:
) cursor.execute(
session.execute( "ALTER TABLE smsgaddresses ADD COLUMN active_ind INTEGER"
text("ALTER TABLE offers ADD COLUMN rate_negotiable INTEGER") )
) cursor.execute(
db_version += 1 "ALTER TABLE smsgaddresses ADD COLUMN created_at INTEGER"
elif current_version == 13: )
db_version += 1 cursor.execute("ALTER TABLE smsgaddresses ADD COLUMN note VARCHAR")
session.execute( cursor.execute("ALTER TABLE smsgaddresses ADD COLUMN pubkey VARCHAR")
text( cursor.execute(
"UPDATE smsgaddresses SET active_ind = 1, created_at = 1"
)
cursor.execute("ALTER TABLE offers ADD COLUMN addr_to VARCHAR")
cursor.execute(f'UPDATE offers SET addr_to = "{self.network_addr}"')
db_version += 1
elif current_version == 11:
cursor.execute(
"ALTER TABLE bids ADD COLUMN chain_a_height_start INTEGER"
)
cursor.execute(
"ALTER TABLE bids ADD COLUMN chain_b_height_start INTEGER"
)
cursor.execute("ALTER TABLE bids ADD COLUMN protocol_version INTEGER")
cursor.execute("ALTER TABLE offers ADD COLUMN protocol_version INTEGER")
cursor.execute("ALTER TABLE transactions ADD COLUMN tx_data BLOB")
db_version += 1
elif current_version == 12:
cursor.execute(
""" """
CREATE TABLE automationstrategies ( CREATE TABLE knownidentities (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
active_ind INTEGER, address VARCHAR,
label VARCHAR, label VARCHAR,
type_ind INTEGER, publickey BLOB,
only_known_identities INTEGER, num_sent_bids_successful INTEGER,
num_concurrent INTEGER, num_recv_bids_successful INTEGER,
data BLOB, num_sent_bids_rejected INTEGER,
num_recv_bids_rejected INTEGER,
note VARCHAR, num_sent_bids_failed INTEGER,
created_at BIGINT, num_recv_bids_failed INTEGER,
PRIMARY KEY (record_id))""" note VARCHAR,
updated_at BIGINT,
created_at BIGINT,
PRIMARY KEY (record_id))"""
) )
) cursor.execute("ALTER TABLE bids ADD COLUMN reject_code INTEGER")
cursor.execute("ALTER TABLE bids ADD COLUMN rate INTEGER")
session.execute( cursor.execute(
text( "ALTER TABLE offers ADD COLUMN amount_negotiable INTEGER"
)
cursor.execute("ALTER TABLE offers ADD COLUMN rate_negotiable INTEGER")
db_version += 1
elif current_version == 13:
db_version += 1
cursor.execute(
""" """
CREATE TABLE automationlinks ( CREATE TABLE automationstrategies (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
active_ind INTEGER, active_ind INTEGER,
label VARCHAR,
type_ind INTEGER,
only_known_identities INTEGER,
num_concurrent INTEGER,
data BLOB,
linked_type INTEGER, note VARCHAR,
linked_id BLOB, created_at BIGINT,
strategy_id INTEGER, PRIMARY KEY (record_id))"""
data BLOB,
repeat_limit INTEGER,
repeat_count INTEGER,
note VARCHAR,
created_at BIGINT,
PRIMARY KEY (record_id))"""
) )
)
session.execute( cursor.execute(
text(
""" """
CREATE TABLE history ( CREATE TABLE automationlinks (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
concept_type INTEGER, active_ind INTEGER,
concept_id INTEGER,
changed_data BLOB,
note VARCHAR, linked_type INTEGER,
created_at BIGINT, linked_id BLOB,
PRIMARY KEY (record_id))""" strategy_id INTEGER,
data BLOB,
repeat_limit INTEGER,
repeat_count INTEGER,
note VARCHAR,
created_at BIGINT,
PRIMARY KEY (record_id))"""
) )
)
session.execute( cursor.execute(
text(
""" """
CREATE TABLE bidstates ( CREATE TABLE history (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
active_ind INTEGER, concept_type INTEGER,
state_id INTEGER, concept_id INTEGER,
label VARCHAR, changed_data BLOB,
in_progress INTEGER,
note VARCHAR, note VARCHAR,
created_at BIGINT, created_at BIGINT,
PRIMARY KEY (record_id))""" PRIMARY KEY (record_id))"""
) )
)
session.execute(text("ALTER TABLE wallets ADD COLUMN active_ind INTEGER")) cursor.execute(
session.execute( """
text("ALTER TABLE knownidentities ADD COLUMN active_ind INTEGER") CREATE TABLE bidstates (
) record_id INTEGER NOT NULL,
session.execute(text("ALTER TABLE eventqueue RENAME TO actions")) active_ind INTEGER,
session.execute( state_id INTEGER,
text("ALTER TABLE actions RENAME COLUMN event_id TO action_id") label VARCHAR,
) in_progress INTEGER,
session.execute(
text("ALTER TABLE actions RENAME COLUMN event_type TO action_type") note VARCHAR,
) created_at BIGINT,
session.execute( PRIMARY KEY (record_id))"""
text("ALTER TABLE actions RENAME COLUMN event_data TO action_data") )
)
elif current_version == 14: cursor.execute("ALTER TABLE wallets ADD COLUMN active_ind INTEGER")
db_version += 1 cursor.execute(
session.execute( "ALTER TABLE knownidentities ADD COLUMN active_ind INTEGER"
text("ALTER TABLE xmr_swaps ADD COLUMN coin_a_lock_release_msg_id BLOB") )
) cursor.execute("ALTER TABLE eventqueue RENAME TO actions")
session.execute( cursor.execute(
text( "ALTER TABLE actions RENAME COLUMN event_id TO action_id"
)
cursor.execute(
"ALTER TABLE actions RENAME COLUMN event_type TO action_type"
)
cursor.execute(
"ALTER TABLE actions RENAME COLUMN event_data TO action_data"
)
elif current_version == 14:
db_version += 1
cursor.execute(
"ALTER TABLE xmr_swaps ADD COLUMN coin_a_lock_release_msg_id BLOB"
)
cursor.execute(
"ALTER TABLE xmr_swaps RENAME COLUMN coin_a_lock_refund_spend_tx_msg_id TO coin_a_lock_spend_tx_msg_id" "ALTER TABLE xmr_swaps RENAME COLUMN coin_a_lock_refund_spend_tx_msg_id TO coin_a_lock_spend_tx_msg_id"
) )
) elif current_version == 15:
elif current_version == 15: db_version += 1
db_version += 1 cursor.execute(
session.execute(
text(
""" """
CREATE TABLE notifications ( CREATE TABLE notifications (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
active_ind INTEGER, active_ind INTEGER,
event_type INTEGER, event_type INTEGER,
event_data BLOB, event_data BLOB,
created_at BIGINT, created_at BIGINT,
PRIMARY KEY (record_id))""" PRIMARY KEY (record_id))"""
) )
) elif current_version == 16:
elif current_version == 16: db_version += 1
db_version += 1 cursor.execute(
session.execute(
text(
""" """
CREATE TABLE prefunded_transactions ( CREATE TABLE prefunded_transactions (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
active_ind INTEGER, active_ind INTEGER,
created_at BIGINT, created_at BIGINT,
linked_type INTEGER, linked_type INTEGER,
linked_id BLOB, linked_id BLOB,
tx_type INTEGER, tx_type INTEGER,
tx_data BLOB, tx_data BLOB,
used_by BLOB, used_by BLOB,
PRIMARY KEY (record_id))""" PRIMARY KEY (record_id))"""
) )
) elif current_version == 17:
elif current_version == 17: db_version += 1
db_version += 1 cursor.execute(
session.execute(
text(
"ALTER TABLE knownidentities ADD COLUMN automation_override INTEGER" "ALTER TABLE knownidentities ADD COLUMN automation_override INTEGER"
) )
) cursor.execute(
session.execute(
text(
"ALTER TABLE knownidentities ADD COLUMN visibility_override INTEGER" "ALTER TABLE knownidentities ADD COLUMN visibility_override INTEGER"
) )
) cursor.execute("ALTER TABLE knownidentities ADD COLUMN data BLOB")
session.execute(text("ALTER TABLE knownidentities ADD COLUMN data BLOB")) cursor.execute("UPDATE knownidentities SET active_ind = 1")
session.execute(text("UPDATE knownidentities SET active_ind = 1")) elif current_version == 18:
elif current_version == 18: db_version += 1
db_version += 1 cursor.execute("ALTER TABLE xmr_split_data ADD COLUMN addr_from STRING")
session.execute( cursor.execute("ALTER TABLE xmr_split_data ADD COLUMN addr_to STRING")
text("ALTER TABLE xmr_split_data ADD COLUMN addr_from STRING") elif current_version == 19:
) db_version += 1
session.execute( cursor.execute("ALTER TABLE bidstates ADD COLUMN in_error INTEGER")
text("ALTER TABLE xmr_split_data ADD COLUMN addr_to STRING") cursor.execute("ALTER TABLE bidstates ADD COLUMN swap_failed INTEGER")
) cursor.execute("ALTER TABLE bidstates ADD COLUMN swap_ended INTEGER")
elif current_version == 19: elif current_version == 20:
db_version += 1 db_version += 1
session.execute(text("ALTER TABLE bidstates ADD COLUMN in_error INTEGER")) cursor.execute(
session.execute(
text("ALTER TABLE bidstates ADD COLUMN swap_failed INTEGER")
)
session.execute(text("ALTER TABLE bidstates ADD COLUMN swap_ended INTEGER"))
elif current_version == 20:
db_version += 1
session.execute(
text(
""" """
CREATE TABLE message_links ( CREATE TABLE message_links (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
active_ind INTEGER, active_ind INTEGER,
created_at BIGINT, created_at BIGINT,
linked_type INTEGER, linked_type INTEGER,
linked_id BLOB, linked_id BLOB,
msg_type INTEGER, msg_type INTEGER,
msg_sequence INTEGER, msg_sequence INTEGER,
msg_id BLOB, msg_id BLOB,
PRIMARY KEY (record_id))""" PRIMARY KEY (record_id))"""
) )
) cursor.execute("ALTER TABLE offers ADD COLUMN bid_reversed INTEGER")
session.execute(text("ALTER TABLE offers ADD COLUMN bid_reversed INTEGER")) elif current_version == 21:
elif current_version == 21: db_version += 1
db_version += 1 cursor.execute("ALTER TABLE offers ADD COLUMN proof_utxos BLOB")
session.execute(text("ALTER TABLE offers ADD COLUMN proof_utxos BLOB")) cursor.execute("ALTER TABLE bids ADD COLUMN proof_utxos BLOB")
session.execute(text("ALTER TABLE bids ADD COLUMN proof_utxos BLOB")) elif current_version == 22:
elif current_version == 22: db_version += 1
db_version += 1 cursor.execute("ALTER TABLE offers ADD COLUMN amount_to INTEGER")
session.execute(text("ALTER TABLE offers ADD COLUMN amount_to INTEGER")) elif current_version == 23:
elif current_version == 23: db_version += 1
db_version += 1 cursor.execute(
session.execute(
text(
""" """
CREATE TABLE checkedblocks ( CREATE TABLE checkedblocks (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
created_at BIGINT, created_at BIGINT,
coin_type INTEGER, coin_type INTEGER,
block_height INTEGER, block_height INTEGER,
block_hash BLOB, block_hash BLOB,
block_time INTEGER, block_time INTEGER,
PRIMARY KEY (record_id))""" PRIMARY KEY (record_id))"""
) )
) cursor.execute("ALTER TABLE bids ADD COLUMN pkhash_buyer_to BLOB")
session.execute(text("ALTER TABLE bids ADD COLUMN pkhash_buyer_to BLOB")) if current_version != db_version:
if current_version != db_version: self.db_version = db_version
self.db_version = db_version self.setIntKV("db_version", db_version, cursor)
self.setIntKV("db_version", db_version, session) cursor = self.commitDB()
session.commit() self.log.info("Upgraded database to version {}".format(self.db_version))
session.close() continue
session.remove() except Exception as e:
self.log.info("Upgraded database to version {}".format(self.db_version)) self.log.error("Upgrade failed {}".format(e))
continue self.rollbackDB()
finally:
self.closeDB(cursor, commit=False)
break break
if db_version != CURRENT_DB_VERSION: if db_version != CURRENT_DB_VERSION:

View file

@ -1,10 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2023-2024 The BSX Developers # Copyright (c) 2023-2024 The Basicswap Developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
from sqlalchemy.sql import text
from .db import ( from .db import (
Concepts, Concepts,
) )
@ -13,7 +12,7 @@ from .db import (
def remove_expired_data(self, time_offset: int = 0): def remove_expired_data(self, time_offset: int = 0):
now: int = self.getTime() now: int = self.getTime()
try: try:
session = self.openSession() cursor = self.openDB()
active_bids_insert = self.activeBidsQueryStr(now, "", "b2") active_bids_insert = self.activeBidsQueryStr(now, "", "b2")
query_str = f""" query_str = f"""
@ -22,118 +21,94 @@ def remove_expired_data(self, time_offset: int = 0):
""" """
num_offers = 0 num_offers = 0
num_bids = 0 num_bids = 0
offer_rows = session.execute(text(query_str), {"expired_at": now - time_offset}) offer_rows = cursor.execute(query_str, {"expired_at": now - time_offset})
for offer_row in offer_rows: for offer_row in offer_rows:
num_offers += 1 num_offers += 1
bid_rows = session.execute( bid_rows = cursor.execute(
text("SELECT bids.bid_id FROM bids WHERE bids.offer_id = :offer_id"), "SELECT bids.bid_id FROM bids WHERE bids.offer_id = :offer_id",
{"offer_id": offer_row[0]}, {"offer_id": offer_row[0]},
) )
for bid_row in bid_rows: for bid_row in bid_rows:
num_bids += 1 num_bids += 1
session.execute( cursor.execute(
text( "DELETE FROM transactions WHERE transactions.bid_id = :bid_id",
"DELETE FROM transactions WHERE transactions.bid_id = :bid_id"
),
{"bid_id": bid_row[0]}, {"bid_id": bid_row[0]},
) )
session.execute( cursor.execute(
text( "DELETE FROM eventlog WHERE eventlog.linked_type = :type_ind AND eventlog.linked_id = :bid_id",
"DELETE FROM eventlog WHERE eventlog.linked_type = :type_ind AND eventlog.linked_id = :bid_id"
),
{"type_ind": int(Concepts.BID), "bid_id": bid_row[0]}, {"type_ind": int(Concepts.BID), "bid_id": bid_row[0]},
) )
session.execute( cursor.execute(
text( "DELETE FROM automationlinks WHERE automationlinks.linked_type = :type_ind AND automationlinks.linked_id = :bid_id",
"DELETE FROM automationlinks WHERE automationlinks.linked_type = :type_ind AND automationlinks.linked_id = :bid_id"
),
{"type_ind": int(Concepts.BID), "bid_id": bid_row[0]}, {"type_ind": int(Concepts.BID), "bid_id": bid_row[0]},
) )
session.execute( cursor.execute(
text( "DELETE FROM prefunded_transactions WHERE prefunded_transactions.linked_type = :type_ind AND prefunded_transactions.linked_id = :bid_id",
"DELETE FROM prefunded_transactions WHERE prefunded_transactions.linked_type = :type_ind AND prefunded_transactions.linked_id = :bid_id"
),
{"type_ind": int(Concepts.BID), "bid_id": bid_row[0]}, {"type_ind": int(Concepts.BID), "bid_id": bid_row[0]},
) )
session.execute( cursor.execute(
text( "DELETE FROM history WHERE history.concept_type = :type_ind AND history.concept_id = :bid_id",
"DELETE FROM history WHERE history.concept_type = :type_ind AND history.concept_id = :bid_id"
),
{"type_ind": int(Concepts.BID), "bid_id": bid_row[0]}, {"type_ind": int(Concepts.BID), "bid_id": bid_row[0]},
) )
session.execute( cursor.execute(
text("DELETE FROM xmr_swaps WHERE xmr_swaps.bid_id = :bid_id"), "DELETE FROM xmr_swaps WHERE xmr_swaps.bid_id = :bid_id",
{"bid_id": bid_row[0]}, {"bid_id": bid_row[0]},
) )
session.execute( cursor.execute(
text("DELETE FROM actions WHERE actions.linked_id = :bid_id"), "DELETE FROM actions WHERE actions.linked_id = :bid_id",
{"bid_id": bid_row[0]}, {"bid_id": bid_row[0]},
) )
session.execute( cursor.execute(
text("DELETE FROM addresspool WHERE addresspool.bid_id = :bid_id"), "DELETE FROM addresspool WHERE addresspool.bid_id = :bid_id",
{"bid_id": bid_row[0]}, {"bid_id": bid_row[0]},
) )
session.execute( cursor.execute(
text( "DELETE FROM xmr_split_data WHERE xmr_split_data.bid_id = :bid_id",
"DELETE FROM xmr_split_data WHERE xmr_split_data.bid_id = :bid_id"
),
{"bid_id": bid_row[0]}, {"bid_id": bid_row[0]},
) )
session.execute( cursor.execute(
text("DELETE FROM bids WHERE bids.bid_id = :bid_id"), "DELETE FROM bids WHERE bids.bid_id = :bid_id",
{"bid_id": bid_row[0]}, {"bid_id": bid_row[0]},
) )
session.execute( cursor.execute(
text( "DELETE FROM message_links WHERE linked_type = :type_ind AND linked_id = :linked_id",
"DELETE FROM message_links WHERE linked_type = :type_ind AND linked_id = :linked_id"
),
{"type_ind": int(Concepts.BID), "linked_id": bid_row[0]}, {"type_ind": int(Concepts.BID), "linked_id": bid_row[0]},
) )
session.execute( cursor.execute(
text( "DELETE FROM eventlog WHERE eventlog.linked_type = :type_ind AND eventlog.linked_id = :offer_id",
"DELETE FROM eventlog WHERE eventlog.linked_type = :type_ind AND eventlog.linked_id = :offer_id"
),
{"type_ind": int(Concepts.OFFER), "offer_id": offer_row[0]}, {"type_ind": int(Concepts.OFFER), "offer_id": offer_row[0]},
) )
session.execute( cursor.execute(
text( "DELETE FROM automationlinks WHERE automationlinks.linked_type = :type_ind AND automationlinks.linked_id = :offer_id",
"DELETE FROM automationlinks WHERE automationlinks.linked_type = :type_ind AND automationlinks.linked_id = :offer_id"
),
{"type_ind": int(Concepts.OFFER), "offer_id": offer_row[0]}, {"type_ind": int(Concepts.OFFER), "offer_id": offer_row[0]},
) )
session.execute( cursor.execute(
text( "DELETE FROM prefunded_transactions WHERE prefunded_transactions.linked_type = :type_ind AND prefunded_transactions.linked_id = :offer_id",
"DELETE FROM prefunded_transactions WHERE prefunded_transactions.linked_type = :type_ind AND prefunded_transactions.linked_id = :offer_id"
),
{"type_ind": int(Concepts.OFFER), "offer_id": offer_row[0]}, {"type_ind": int(Concepts.OFFER), "offer_id": offer_row[0]},
) )
session.execute( cursor.execute(
text( "DELETE FROM history WHERE history.concept_type = :type_ind AND history.concept_id = :offer_id",
"DELETE FROM history WHERE history.concept_type = :type_ind AND history.concept_id = :offer_id"
),
{"type_ind": int(Concepts.OFFER), "offer_id": offer_row[0]}, {"type_ind": int(Concepts.OFFER), "offer_id": offer_row[0]},
) )
session.execute( cursor.execute(
text("DELETE FROM xmr_offers WHERE xmr_offers.offer_id = :offer_id"), "DELETE FROM xmr_offers WHERE xmr_offers.offer_id = :offer_id",
{"offer_id": offer_row[0]}, {"offer_id": offer_row[0]},
) )
session.execute( cursor.execute(
text("DELETE FROM sentoffers WHERE sentoffers.offer_id = :offer_id"), "DELETE FROM sentoffers WHERE sentoffers.offer_id = :offer_id",
{"offer_id": offer_row[0]}, {"offer_id": offer_row[0]},
) )
session.execute( cursor.execute(
text("DELETE FROM actions WHERE actions.linked_id = :offer_id"), "DELETE FROM actions WHERE actions.linked_id = :offer_id",
{"offer_id": offer_row[0]}, {"offer_id": offer_row[0]},
) )
session.execute( cursor.execute(
text("DELETE FROM offers WHERE offers.offer_id = :offer_id"), "DELETE FROM offers WHERE offers.offer_id = :offer_id",
{"offer_id": offer_row[0]}, {"offer_id": offer_row[0]},
) )
session.execute( cursor.execute(
text( "DELETE FROM message_links WHERE linked_type = :type_ind AND linked_id = :offer_id",
"DELETE FROM message_links WHERE linked_type = :type_ind AND linked_id = :offer_id"
),
{"type_ind": int(Concepts.OFFER), "offer_id": offer_row[0]}, {"type_ind": int(Concepts.OFFER), "offer_id": offer_row[0]},
) )
@ -147,10 +122,10 @@ def remove_expired_data(self, time_offset: int = 0):
) )
) )
session.execute( cursor.execute(
text("DELETE FROM checkedblocks WHERE created_at <= :expired_at"), "DELETE FROM checkedblocks WHERE created_at <= :expired_at",
{"expired_at": now - time_offset}, {"expired_at": now - time_offset},
) )
finally: finally:
self.closeSession(session) self.closeDB(cursor)

View file

@ -612,11 +612,11 @@ class BCHInterface(BTCInterface):
prevout_script: bytes, prevout_script: bytes,
prevout_value: int, prevout_value: int,
) -> bool: ) -> bool:
# simple ecdsa signature verification # Simple ecdsa signature verification
return self.verifyDataSig(tx_bytes, sig, K) return self.verifyDataSig(tx_bytes, sig, K)
def verifyDataSig(self, data: bytes, sig: bytes, K: bytes) -> bool: def verifyDataSig(self, data: bytes, sig: bytes, K: bytes) -> bool:
# simple ecdsa signature verification # Simple ecdsa signature verification
pubkey = PublicKey(K) pubkey = PublicKey(K)
return pubkey.verify(sig, sha256(data), hasher=None) return pubkey.verify(sig, sha256(data), hasher=None)
@ -637,7 +637,7 @@ class BCHInterface(BTCInterface):
return signature, mining_fee, out_1, out_2, public_key, timelock return signature, mining_fee, out_1, out_2, public_key, timelock
def extractScriptLockScriptValues(self, script_bytes): def extractScriptLockScriptValues(self, script_bytes):
# see BCHInterface.genScriptLockTxScript for reference # See BCHInterface.genScriptLockTxScript for reference
o = 0 o = 0
@ -1071,6 +1071,9 @@ class BCHInterface(BTCInterface):
) )
return out_1 return out_1
def lockNonSegwitPrevouts(self) -> None:
pass
def createMercyTx( def createMercyTx(
self, self,
refund_swipe_tx_bytes: bytes, refund_swipe_tx_bytes: bytes,

View file

@ -1158,7 +1158,8 @@ class BTCInterface(Secp256k1Interface):
def fundTx(self, tx: bytes, feerate) -> bytes: def fundTx(self, tx: bytes, feerate) -> bytes:
feerate_str = self.format_amount(feerate) feerate_str = self.format_amount(feerate)
# TODO: unlock unspents if bid cancelled # TODO: Unlock unspents if bid cancelled
# TODO: Manually select only segwit prevouts
options = { options = {
"lockUnspents": True, "lockUnspents": True,
"feeRate": feerate_str, "feeRate": feerate_str,
@ -1166,6 +1167,27 @@ class BTCInterface(Secp256k1Interface):
rv = self.rpc_wallet("fundrawtransaction", [tx.hex(), options]) rv = self.rpc_wallet("fundrawtransaction", [tx.hex(), options])
return bytes.fromhex(rv["hex"]) return bytes.fromhex(rv["hex"])
def lockNonSegwitPrevouts(self) -> None:
# For tests
unspent = self.rpc_wallet("listunspent")
to_lock = []
for u in unspent:
if u.get("spendable", False) is False:
continue
if "desc" in u:
desc = u["desc"]
if self.use_p2shp2wsh():
if not desc.startswith("sh(wpkh"):
to_lock.append({"txid": u["txid"], "vout": u["vout"]})
else:
if not desc.startswith("wpkh"):
to_lock.append({"txid": u["txid"], "vout": u["vout"]})
if len(to_lock) > 0:
self._log.debug(f"Locking {len(to_lock)} non segwit prevouts")
self.rpc_wallet("lockunspent", [False, to_lock])
def listInputs(self, tx_bytes: bytes): def listInputs(self, tx_bytes: bytes):
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)

View file

@ -119,12 +119,12 @@ def extractScriptSecretHash(script):
return script[7:39] return script[7:39]
def redeemITx(self, bid_id: bytes, session): def redeemITx(self, bid_id: bytes, cursor):
bid, offer = self.getBidAndOffer(bid_id, session) bid, offer = self.getBidAndOffer(bid_id, cursor)
ci_from = self.ci(offer.coin_from) ci_from = self.ci(offer.coin_from)
txn = self.createRedeemTxn( txn = self.createRedeemTxn(
ci_from.coin_type(), bid, for_txn_type="initiate", session=session ci_from.coin_type(), bid, for_txn_type="initiate", cursor=cursor
) )
txid = ci_from.publishTx(bytes.fromhex(txn)) txid = ci_from.publishTx(bytes.fromhex(txn))
@ -135,7 +135,7 @@ def redeemITx(self, bid_id: bytes, session):
ci_from.coin_name(), ci_from.coin_name(),
bid_id.hex(), bid_id.hex(),
) )
self.logEvent(Concepts.BID, bid_id, EventLogTypes.ITX_REDEEM_PUBLISHED, "", session) self.logEvent(Concepts.BID, bid_id, EventLogTypes.ITX_REDEEM_PUBLISHED, "", cursor)
class AtomicSwapInterface(ProtocolInterface): class AtomicSwapInterface(ProtocolInterface):

View file

@ -42,17 +42,15 @@ def addLockRefundSigs(self, xmr_swap, ci):
xmr_swap.a_lock_refund_tx = signed_tx xmr_swap.a_lock_refund_tx = signed_tx
def recoverNoScriptTxnWithKey(self, bid_id: bytes, encoded_key, session=None): def recoverNoScriptTxnWithKey(self, bid_id: bytes, encoded_key, cursor=None):
self.log.info(f"Manually recovering {bid_id.hex()}") self.log.info(f"Manually recovering {bid_id.hex()}")
# Manually recover txn if other key is known # Manually recover txn if other key is known
try: try:
use_session = self.openSession(session) use_cursor = self.openDB(cursor)
bid, xmr_swap = self.getXmrBidFromSession(use_session, bid_id) bid, xmr_swap = self.getXmrBidFromSession(use_cursor, bid_id)
ensure(bid, "Bid not found: {}.".format(bid_id.hex())) ensure(bid, "Bid not found: {}.".format(bid_id.hex()))
ensure(xmr_swap, "Adaptor-sig swap not found: {}.".format(bid_id.hex())) ensure(xmr_swap, "Adaptor-sig swap not found: {}.".format(bid_id.hex()))
offer, xmr_offer = self.getXmrOfferFromSession( offer, xmr_offer = self.getXmrOfferFromSession(use_cursor, bid.offer_id)
use_session, bid.offer_id, sent=False
)
ensure(offer, "Offer not found: {}.".format(bid.offer_id.hex())) ensure(offer, "Offer not found: {}.".format(bid.offer_id.hex()))
ensure(xmr_offer, "Adaptor-sig offer not found: {}.".format(bid.offer_id.hex())) ensure(xmr_offer, "Adaptor-sig offer not found: {}.".format(bid.offer_id.hex()))
@ -97,10 +95,10 @@ def recoverNoScriptTxnWithKey(self, bid_id: bytes, encoded_key, session=None):
raise ValueError(err_msg) raise ValueError(err_msg)
if ci_follower.coin_type() in (Coins.XMR, Coins.WOW): if ci_follower.coin_type() in (Coins.XMR, Coins.WOW):
address_to = self.getCachedMainWalletAddress(ci_follower, use_session) address_to = self.getCachedMainWalletAddress(ci_follower, use_cursor)
else: else:
address_to = self.getCachedStealthAddressForCoin( address_to = self.getCachedStealthAddressForCoin(
ci_follower.coin_type(), use_session ci_follower.coin_type(), use_cursor
) )
amount = bid.amount_to amount = bid.amount_to
lock_tx_vout = bid.getLockTXBVout() lock_tx_vout = bid.getLockTXBVout()
@ -125,17 +123,17 @@ def recoverNoScriptTxnWithKey(self, bid_id: bytes, encoded_key, session=None):
bid.bid_id, bid.bid_id,
EventLogTypes.LOCK_TX_B_SPEND_TX_PUBLISHED, EventLogTypes.LOCK_TX_B_SPEND_TX_PUBLISHED,
txid.hex(), txid.hex(),
use_session, use_cursor,
) )
use_session.commit() self.commitDB()
return txid return txid
except Exception as e: except Exception as e:
self.log.error(traceback.format_exc()) self.log.error(traceback.format_exc())
raise (e) raise (e)
finally: finally:
if session is None: if cursor is None:
self.closeSession(use_session, commit=False) self.closeDB(use_cursor, commit=False)
def getChainBSplitKey(swap_client, bid, xmr_swap, offer): def getChainBSplitKey(swap_client, bid, xmr_swap, offer):

View file

@ -898,7 +898,7 @@ def page_offers(self, url_split, post_string, sent=False):
sent = True sent = True
else: else:
sent = False sent = False
offers = swap_client.listOffers(sent, filters, with_bid_info=True) offers = swap_client.listOffers(sent, filters)
now: int = swap_client.getTime() now: int = swap_client.getTime()
formatted_offers = [] formatted_offers = []
@ -906,7 +906,7 @@ def page_offers(self, url_split, post_string, sent=False):
tla_to = "" tla_to = ""
for row in offers: for row in offers:
o, completed_amount = row o = row
ci_from = swap_client.ci(Coins(o.coin_from)) ci_from = swap_client.ci(Coins(o.coin_from))
ci_to = swap_client.ci(Coins(o.coin_to)) ci_to = swap_client.ci(Coins(o.coin_to))
is_expired = o.expire_at <= now is_expired = o.expire_at <= now
@ -932,7 +932,7 @@ def page_offers(self, url_split, post_string, sent=False):
"Public" if o.addr_to == swap_client.network_addr else o.addr_to, "Public" if o.addr_to == swap_client.network_addr else o.addr_to,
o.addr_from, o.addr_from,
o.was_sent, o.was_sent,
ci_from.format_amount(completed_amount), None, # placeholder, was completed_amount
is_expired, is_expired,
o.active_ind, o.active_ind,
formatted_expired_at, formatted_expired_at,

View file

@ -5,6 +5,7 @@
- BCH support. - BCH support.
- Mercy outputs on swipe txns of BTC descended coins. - Mercy outputs on swipe txns of BTC descended coins.
- Disable by setting 'altruistic' to false in basicswap.json - Disable by setting 'altruistic' to false in basicswap.json
- Removed sqlalchemy.

View file

@ -111,17 +111,6 @@
(home-page "https://github.com/basicswap/coincurve") (home-page "https://github.com/basicswap/coincurve")
(license license:bsd-3))) (license license:bsd-3)))
(define python-sqlalchemy-1.4.39
(package
(inherit python-sqlalchemy)
(version "1.4.39")
(source
(origin
(method url-fetch)
(uri (pypi-uri "SQLAlchemy" version))
(sha256
(base32 "09sx2lghywnm7qj1xm8xc3xrgj40bndfh2hbiaq4cfvm71h8k541"))))))
(define-public basicswap (define-public basicswap
(package (package
(name "basicswap") (name "basicswap")
@ -153,7 +142,6 @@
python-coincurve-basicswap python-coincurve-basicswap
python-pycryptodome python-pycryptodome
python-pytest python-pytest
python-sqlalchemy
python-pyzmq python-pyzmq
python-gnupg python-gnupg
python-jinja2 python-jinja2

View file

@ -1,5 +1,4 @@
pyzmq==26.2.0 pyzmq==26.2.0
SQLAlchemy==2.0.35
python-gnupg==0.5.3 python-gnupg==0.5.3
Jinja2==3.1.4 Jinja2==3.1.4
pycryptodome==3.21.0 pycryptodome==3.21.0

View file

@ -80,147 +80,72 @@ cffi==1.17.1 \
coincurve @ https://github.com/basicswap/coincurve/archive/refs/tags/basicswap_v0.2.zip \ coincurve @ https://github.com/basicswap/coincurve/archive/refs/tags/basicswap_v0.2.zip \
--hash=sha256:c309deef22c929c9ab5b3adf7adbda940bffcea6c6ec7c66202d6c3d4e3ceb79 --hash=sha256:c309deef22c929c9ab5b3adf7adbda940bffcea6c6ec7c66202d6c3d4e3ceb79
# via -r requirements.in # via -r requirements.in
greenlet==3.1.1 \
--hash=sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e \
--hash=sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7 \
--hash=sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01 \
--hash=sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1 \
--hash=sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159 \
--hash=sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563 \
--hash=sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83 \
--hash=sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9 \
--hash=sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395 \
--hash=sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa \
--hash=sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942 \
--hash=sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1 \
--hash=sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441 \
--hash=sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22 \
--hash=sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9 \
--hash=sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0 \
--hash=sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba \
--hash=sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3 \
--hash=sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1 \
--hash=sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6 \
--hash=sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291 \
--hash=sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39 \
--hash=sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d \
--hash=sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467 \
--hash=sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475 \
--hash=sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef \
--hash=sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c \
--hash=sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511 \
--hash=sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c \
--hash=sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822 \
--hash=sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a \
--hash=sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8 \
--hash=sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d \
--hash=sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01 \
--hash=sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145 \
--hash=sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80 \
--hash=sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13 \
--hash=sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e \
--hash=sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b \
--hash=sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1 \
--hash=sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef \
--hash=sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc \
--hash=sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff \
--hash=sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120 \
--hash=sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437 \
--hash=sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd \
--hash=sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981 \
--hash=sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36 \
--hash=sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a \
--hash=sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798 \
--hash=sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7 \
--hash=sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761 \
--hash=sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0 \
--hash=sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e \
--hash=sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af \
--hash=sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa \
--hash=sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c \
--hash=sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42 \
--hash=sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e \
--hash=sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81 \
--hash=sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e \
--hash=sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617 \
--hash=sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc \
--hash=sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de \
--hash=sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111 \
--hash=sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383 \
--hash=sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70 \
--hash=sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6 \
--hash=sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4 \
--hash=sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011 \
--hash=sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803 \
--hash=sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79 \
--hash=sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f
# via sqlalchemy
jinja2==3.1.4 \ jinja2==3.1.4 \
--hash=sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369 \ --hash=sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369 \
--hash=sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d --hash=sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d
# via -r requirements.in # via -r requirements.in
markupsafe==3.0.1 \ markupsafe==3.0.2 \
--hash=sha256:0778de17cff1acaeccc3ff30cd99a3fd5c50fc58ad3d6c0e0c4c58092b859396 \ --hash=sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4 \
--hash=sha256:0f84af7e813784feb4d5e4ff7db633aba6c8ca64a833f61d8e4eade234ef0c38 \ --hash=sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30 \
--hash=sha256:17b2aea42a7280db02ac644db1d634ad47dcc96faf38ab304fe26ba2680d359a \ --hash=sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0 \
--hash=sha256:242d6860f1fd9191aef5fae22b51c5c19767f93fb9ead4d21924e0bcb17619d8 \ --hash=sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9 \
--hash=sha256:244dbe463d5fb6d7ce161301a03a6fe744dac9072328ba9fc82289238582697b \ --hash=sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396 \
--hash=sha256:26627785a54a947f6d7336ce5963569b5d75614619e75193bdb4e06e21d447ad \ --hash=sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13 \
--hash=sha256:2a4b34a8d14649315c4bc26bbfa352663eb51d146e35eef231dd739d54a5430a \ --hash=sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028 \
--hash=sha256:2ae99f31f47d849758a687102afdd05bd3d3ff7dbab0a8f1587981b58a76152a \ --hash=sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca \
--hash=sha256:312387403cd40699ab91d50735ea7a507b788091c416dd007eac54434aee51da \ --hash=sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557 \
--hash=sha256:3341c043c37d78cc5ae6e3e305e988532b072329639007fd408a476642a89fd6 \ --hash=sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832 \
--hash=sha256:33d1c36b90e570ba7785dacd1faaf091203d9942bc036118fab8110a401eb1a8 \ --hash=sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0 \
--hash=sha256:3e683ee4f5d0fa2dde4db77ed8dd8a876686e3fc417655c2ece9a90576905344 \ --hash=sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b \
--hash=sha256:3ffb4a8e7d46ed96ae48805746755fadd0909fea2306f93d5d8233ba23dda12a \ --hash=sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579 \
--hash=sha256:40621d60d0e58aa573b68ac5e2d6b20d44392878e0bfc159012a5787c4e35bc8 \ --hash=sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a \
--hash=sha256:40f1e10d51c92859765522cbd79c5c8989f40f0419614bcdc5015e7b6bf97fc5 \ --hash=sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c \
--hash=sha256:45d42d132cff577c92bfba536aefcfea7e26efb975bd455db4e6602f5c9f45e7 \ --hash=sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff \
--hash=sha256:48488d999ed50ba8d38c581d67e496f955821dc183883550a6fbc7f1aefdc170 \ --hash=sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c \
--hash=sha256:4935dd7883f1d50e2ffecca0aa33dc1946a94c8f3fdafb8df5c330e48f71b132 \ --hash=sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22 \
--hash=sha256:4c2d64fdba74ad16138300815cfdc6ab2f4647e23ced81f59e940d7d4a1469d9 \ --hash=sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094 \
--hash=sha256:4c8817557d0de9349109acb38b9dd570b03cc5014e8aabf1cbddc6e81005becd \ --hash=sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb \
--hash=sha256:4ffaaac913c3f7345579db4f33b0020db693f302ca5137f106060316761beea9 \ --hash=sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e \
--hash=sha256:5a4cb365cb49b750bdb60b846b0c0bc49ed62e59a76635095a179d440540c346 \ --hash=sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5 \
--hash=sha256:62fada2c942702ef8952754abfc1a9f7658a4d5460fabe95ac7ec2cbe0d02abc \ --hash=sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a \
--hash=sha256:67c519635a4f64e495c50e3107d9b4075aec33634272b5db1cde839e07367589 \ --hash=sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d \
--hash=sha256:6a54c43d3ec4cf2a39f4387ad044221c66a376e58c0d0e971d47c475ba79c6b5 \ --hash=sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a \
--hash=sha256:7044312a928a66a4c2a22644147bc61a199c1709712069a344a3fb5cfcf16915 \ --hash=sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b \
--hash=sha256:730d86af59e0e43ce277bb83970530dd223bf7f2a838e086b50affa6ec5f9295 \ --hash=sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8 \
--hash=sha256:800100d45176652ded796134277ecb13640c1a537cad3b8b53da45aa96330453 \ --hash=sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225 \
--hash=sha256:80fcbf3add8790caddfab6764bde258b5d09aefbe9169c183f88a7410f0f6dea \ --hash=sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c \
--hash=sha256:82b5dba6eb1bcc29cc305a18a3c5365d2af06ee71b123216416f7e20d2a84e5b \ --hash=sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144 \
--hash=sha256:852dc840f6d7c985603e60b5deaae1d89c56cb038b577f6b5b8c808c97580f1d \ --hash=sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f \
--hash=sha256:8ad4ad1429cd4f315f32ef263c1342166695fad76c100c5d979c45d5570ed58b \ --hash=sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87 \
--hash=sha256:8ae369e84466aa70f3154ee23c1451fda10a8ee1b63923ce76667e3077f2b0c4 \ --hash=sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d \
--hash=sha256:93e8248d650e7e9d49e8251f883eed60ecbc0e8ffd6349e18550925e31bd029b \ --hash=sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93 \
--hash=sha256:973a371a55ce9ed333a3a0f8e0bcfae9e0d637711534bcb11e130af2ab9334e7 \ --hash=sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf \
--hash=sha256:9ba25a71ebf05b9bb0e2ae99f8bc08a07ee8e98c612175087112656ca0f5c8bf \ --hash=sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158 \
--hash=sha256:a10860e00ded1dd0a65b83e717af28845bb7bd16d8ace40fe5531491de76b79f \ --hash=sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84 \
--hash=sha256:a4792d3b3a6dfafefdf8e937f14906a51bd27025a36f4b188728a73382231d91 \ --hash=sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb \
--hash=sha256:a7420ceda262dbb4b8d839a4ec63d61c261e4e77677ed7c66c99f4e7cb5030dd \ --hash=sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48 \
--hash=sha256:ad91738f14eb8da0ff82f2acd0098b6257621410dcbd4df20aaa5b4233d75a50 \ --hash=sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171 \
--hash=sha256:b6a387d61fe41cdf7ea95b38e9af11cfb1a63499af2759444b99185c4ab33f5b \ --hash=sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c \
--hash=sha256:b954093679d5750495725ea6f88409946d69cfb25ea7b4c846eef5044194f583 \ --hash=sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6 \
--hash=sha256:bbde71a705f8e9e4c3e9e33db69341d040c827c7afa6789b14c6e16776074f5a \ --hash=sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd \
--hash=sha256:beeebf760a9c1f4c07ef6a53465e8cfa776ea6a2021eda0d0417ec41043fe984 \ --hash=sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d \
--hash=sha256:c91b394f7601438ff79a4b93d16be92f216adb57d813a78be4446fe0f6bc2d8c \ --hash=sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1 \
--hash=sha256:c97ff7fedf56d86bae92fa0a646ce1a0ec7509a7578e1ed238731ba13aabcd1c \ --hash=sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d \
--hash=sha256:cb53e2a99df28eee3b5f4fea166020d3ef9116fdc5764bc5117486e6d1211b25 \ --hash=sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca \
--hash=sha256:cbf445eb5628981a80f54087f9acdbf84f9b7d862756110d172993b9a5ae81aa \ --hash=sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a \
--hash=sha256:d06b24c686a34c86c8c1fba923181eae6b10565e4d80bdd7bc1c8e2f11247aa4 \ --hash=sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29 \
--hash=sha256:d98e66a24497637dd31ccab090b34392dddb1f2f811c4b4cd80c230205c074a3 \ --hash=sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe \
--hash=sha256:db15ce28e1e127a0013dfb8ac243a8e392db8c61eae113337536edb28bdc1f97 \ --hash=sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798 \
--hash=sha256:db842712984e91707437461930e6011e60b39136c7331e971952bb30465bc1a1 \ --hash=sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c \
--hash=sha256:e24bfe89c6ac4c31792793ad9f861b8f6dc4546ac6dc8f1c9083c7c4f2b335cd \ --hash=sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8 \
--hash=sha256:e81c52638315ff4ac1b533d427f50bc0afc746deb949210bc85f05d4f15fd772 \ --hash=sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f \
--hash=sha256:e9393357f19954248b00bed7c56f29a25c930593a77630c719653d51e7669c2a \ --hash=sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f \
--hash=sha256:ee3941769bd2522fe39222206f6dd97ae83c442a94c90f2b7a25d847d40f4729 \ --hash=sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a \
--hash=sha256:f31ae06f1328595d762c9a2bf29dafd8621c7d3adc130cbb46278079758779ca \ --hash=sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178 \
--hash=sha256:f94190df587738280d544971500b9cafc9b950d32efcb1fba9ac10d84e6aa4e6 \ --hash=sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0 \
--hash=sha256:fa7d686ed9883f3d664d39d5a8e74d3c5f63e603c2e3ff0abcba23eac6542635 \ --hash=sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79 \
--hash=sha256:fb532dd9900381d2e8f48172ddc5a59db4c445a11b9fab40b3b786da40d3b56b \ --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 \
--hash=sha256:fe32482b37b4b00c7a52a07211b479653b7fe4f22b2e481b9a9b099d8a430f2f --hash=sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50
# via jinja2 # via jinja2
pycparser==2.22 \ pycparser==2.22 \
--hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \
@ -380,58 +305,3 @@ pyzmq==26.2.0 \
--hash=sha256:fc4f7a173a5609631bb0c42c23d12c49df3966f89f496a51d3eb0ec81f4519d6 \ --hash=sha256:fc4f7a173a5609631bb0c42c23d12c49df3966f89f496a51d3eb0ec81f4519d6 \
--hash=sha256:fdb5b3e311d4d4b0eb8b3e8b4d1b0a512713ad7e6a68791d0923d1aec433d919 --hash=sha256:fdb5b3e311d4d4b0eb8b3e8b4d1b0a512713ad7e6a68791d0923d1aec433d919
# via -r requirements.in # via -r requirements.in
sqlalchemy==2.0.35 \
--hash=sha256:016b2e665f778f13d3c438651dd4de244214b527a275e0acf1d44c05bc6026a9 \
--hash=sha256:032d979ce77a6c2432653322ba4cbeabf5a6837f704d16fa38b5a05d8e21fa00 \
--hash=sha256:0375a141e1c0878103eb3d719eb6d5aa444b490c96f3fedab8471c7f6ffe70ee \
--hash=sha256:042622a5306c23b972192283f4e22372da3b8ddf5f7aac1cc5d9c9b222ab3ff6 \
--hash=sha256:05c3f58cf91683102f2f0265c0db3bd3892e9eedabe059720492dbaa4f922da1 \
--hash=sha256:0630774b0977804fba4b6bbea6852ab56c14965a2b0c7fc7282c5f7d90a1ae72 \
--hash=sha256:0f9f3f9a3763b9c4deb8c5d09c4cc52ffe49f9876af41cc1b2ad0138878453cf \
--hash=sha256:1b56961e2d31389aaadf4906d453859f35302b4eb818d34a26fab72596076bb8 \
--hash=sha256:22b83aed390e3099584b839b93f80a0f4a95ee7f48270c97c90acd40ee646f0b \
--hash=sha256:25b0f63e7fcc2a6290cb5f7f5b4fc4047843504983a28856ce9b35d8f7de03cc \
--hash=sha256:2a275a806f73e849e1c309ac11108ea1a14cd7058577aba962cd7190e27c9e3c \
--hash=sha256:2ab3f0336c0387662ce6221ad30ab3a5e6499aab01b9790879b6578fd9b8faa1 \
--hash=sha256:2e795c2f7d7249b75bb5f479b432a51b59041580d20599d4e112b5f2046437a3 \
--hash=sha256:3655af10ebcc0f1e4e06c5900bb33e080d6a1fa4228f502121f28a3b1753cde5 \
--hash=sha256:4668bd8faf7e5b71c0319407b608f278f279668f358857dbfd10ef1954ac9f90 \
--hash=sha256:4c31943b61ed8fdd63dfd12ccc919f2bf95eefca133767db6fbbd15da62078ec \
--hash=sha256:4fdcd72a789c1c31ed242fd8c1bcd9ea186a98ee8e5408a50e610edfef980d71 \
--hash=sha256:627dee0c280eea91aed87b20a1f849e9ae2fe719d52cbf847c0e0ea34464b3f7 \
--hash=sha256:67219632be22f14750f0d1c70e62f204ba69d28f62fd6432ba05ab295853de9b \
--hash=sha256:6921ee01caf375363be5e9ae70d08ce7ca9d7e0e8983183080211a062d299468 \
--hash=sha256:69683e02e8a9de37f17985905a5eca18ad651bf592314b4d3d799029797d0eb3 \
--hash=sha256:6a93c5a0dfe8d34951e8a6f499a9479ffb9258123551fa007fc708ae2ac2bc5e \
--hash=sha256:732e026240cdd1c1b2e3ac515c7a23820430ed94292ce33806a95869c46bd139 \
--hash=sha256:7befc148de64b6060937231cbff8d01ccf0bfd75aa26383ffdf8d82b12ec04ff \
--hash=sha256:890da8cd1941fa3dab28c5bac3b9da8502e7e366f895b3b8e500896f12f94d11 \
--hash=sha256:89b64cd8898a3a6f642db4eb7b26d1b28a497d4022eccd7717ca066823e9fb01 \
--hash=sha256:8a6219108a15fc6d24de499d0d515c7235c617b2540d97116b663dade1a54d62 \
--hash=sha256:8cdf1a0dbe5ced887a9b127da4ffd7354e9c1a3b9bb330dce84df6b70ccb3a8d \
--hash=sha256:8d625eddf7efeba2abfd9c014a22c0f6b3796e0ffb48f5d5ab106568ef01ff5a \
--hash=sha256:93a71c8601e823236ac0e5d087e4f397874a421017b3318fd92c0b14acf2b6db \
--hash=sha256:9509c4123491d0e63fb5e16199e09f8e262066e58903e84615c301dde8fa2e87 \
--hash=sha256:a29762cd3d116585278ffb2e5b8cc311fb095ea278b96feef28d0b423154858e \
--hash=sha256:a62dd5d7cc8626a3634208df458c5fe4f21200d96a74d122c83bc2015b333bc1 \
--hash=sha256:ada603db10bb865bbe591939de854faf2c60f43c9b763e90f653224138f910d9 \
--hash=sha256:aee110e4ef3c528f3abbc3c2018c121e708938adeeff9006428dd7c8555e9b3f \
--hash=sha256:b76d63495b0508ab9fc23f8152bac63205d2a704cd009a2b0722f4c8e0cba8e0 \
--hash=sha256:c0d8326269dbf944b9201911b0d9f3dc524d64779a07518199a58384c3d37a44 \
--hash=sha256:c41411e192f8d3ea39ea70e0fae48762cd11a2244e03751a98bd3c0ca9a4e936 \
--hash=sha256:c68fe3fcde03920c46697585620135b4ecfdfc1ed23e75cc2c2ae9f8502c10b8 \
--hash=sha256:cb8bea573863762bbf45d1e13f87c2d2fd32cee2dbd50d050f83f87429c9e1ea \
--hash=sha256:cc32b2990fc34380ec2f6195f33a76b6cdaa9eecf09f0c9404b74fc120aef36f \
--hash=sha256:ccae5de2a0140d8be6838c331604f91d6fafd0735dbdcee1ac78fc8fbaba76b4 \
--hash=sha256:d299797d75cd747e7797b1b41817111406b8b10a4f88b6e8fe5b5e59598b43b0 \
--hash=sha256:e04b622bb8a88f10e439084486f2f6349bf4d50605ac3e445869c7ea5cf0fa8c \
--hash=sha256:e11d7ea4d24f0a262bccf9a7cd6284c976c5369dac21db237cff59586045ab9f \
--hash=sha256:e21f66748ab725ade40fa7af8ec8b5019c68ab00b929f6643e1b1af461eddb60 \
--hash=sha256:eb60b026d8ad0c97917cb81d3662d0b39b8ff1335e3fabb24984c6acd0c900a2 \
--hash=sha256:f021d334f2ca692523aaf7bbf7592ceff70c8594fad853416a81d66b35e3abf9 \
--hash=sha256:f552023710d4b93d8fb29a91fadf97de89c5926c6bd758897875435f2a939f33
# via -r requirements.in
typing-extensions==4.12.2 \
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
# via sqlalchemy

View file

@ -1414,6 +1414,16 @@ class BasicSwapTest(TestFunctions):
) )
assert len(tx_wallet["blockhash"]) == 64 assert len(tx_wallet["blockhash"]) == 64
def test_01_0_lock_bad_prevouts(self):
logging.info(
"---------- Test {} lock_bad_prevouts".format(self.test_coin_from.name)
)
# Lock non segwit prevouts created in earlier tests
for i in range(2):
ci = self.swap_clients[i].ci(self.test_coin_from)
if hasattr(ci, "lockNonSegwitPrevouts"):
ci.lockNonSegwitPrevouts()
def test_01_a_full_swap(self): def test_01_a_full_swap(self):
if not self.has_segwit: if not self.has_segwit:
return return