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,14 +35,12 @@ 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: if data_version < 1:
session.add( self.add(
AutomationStrategy( AutomationStrategy(
active_ind=1, active_ind=1,
label="Accept All", label="Accept All",
@ -53,9 +50,10 @@ def upgradeDatabaseData(self, data_version):
).encode("utf-8"), ).encode("utf-8"),
only_known_identities=False, only_known_identities=False,
created_at=now, created_at=now,
),
cursor,
) )
) self.add(
session.add(
AutomationStrategy( AutomationStrategy(
active_ind=1, active_ind=1,
label="Accept Known", label="Accept Known",
@ -66,11 +64,12 @@ def upgradeDatabaseData(self, data_version):
only_known_identities=True, only_known_identities=True,
note="Accept bids from identities with previously successful swaps only", note="Accept bids from identities with previously successful swaps only",
created_at=now, created_at=now,
) ),
cursor,
) )
for state in BidStates: for state in BidStates:
session.add( self.add(
BidState( BidState(
active_ind=1, active_ind=1,
state_id=int(state), state_id=int(state),
@ -80,7 +79,8 @@ def upgradeDatabaseData(self, data_version):
swap_ended=isFinalBidState(state), swap_ended=isFinalBidState(state),
label=strBidState(state), label=strBidState(state),
created_at=now, created_at=now,
) ),
cursor,
) )
if data_version > 0 and data_version < 2: if data_version > 0 and data_version < 2:
@ -88,22 +88,22 @@ def upgradeDatabaseData(self, data_version):
BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_TX_SIGS, BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_TX_SIGS,
BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX, BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX,
): ):
session.add( self.add(
BidState( BidState(
active_ind=1, active_ind=1,
state_id=int(state), state_id=int(state),
in_progress=isActiveBidState(state), in_progress=isActiveBidState(state),
label=strBidState(state), label=strBidState(state),
created_at=now, created_at=now,
) ),
cursor,
) )
if data_version > 0 and data_version < 3: if data_version > 0 and data_version < 3:
for state in BidStates: for state in BidStates:
in_error = isErrorBidState(state) in_error = isErrorBidState(state)
swap_failed = isFailingBidState(state) swap_failed = isFailingBidState(state)
swap_ended = isFinalBidState(state) swap_ended = isFinalBidState(state)
session.execute( cursor.execute(
text(
"UPDATE bidstates SET in_error = :in_error, swap_failed = :swap_failed, swap_ended = :swap_ended WHERE state_id = :state_id", "UPDATE bidstates SET in_error = :in_error, swap_failed = :swap_failed, swap_ended = :swap_ended WHERE state_id = :state_id",
{ {
"in_error": in_error, "in_error": in_error,
@ -112,13 +112,12 @@ def upgradeDatabaseData(self, data_version):
"state_id": int(state), "state_id": int(state),
}, },
) )
)
if data_version > 0 and data_version < 4: if data_version > 0 and data_version < 4:
for state in ( for state in (
BidStates.BID_REQUEST_SENT, BidStates.BID_REQUEST_SENT,
BidStates.BID_REQUEST_ACCEPTED, BidStates.BID_REQUEST_ACCEPTED,
): ):
session.add( self.add(
BidState( BidState(
active_ind=1, active_ind=1,
state_id=int(state), state_id=int(state),
@ -128,18 +127,18 @@ def upgradeDatabaseData(self, data_version):
swap_ended=isFinalBidState(state), swap_ended=isFinalBidState(state),
label=strBidState(state), label=strBidState(state),
created_at=now, created_at=now,
) ),
cursor,
) )
self.db_data_version = CURRENT_DB_DATA_VERSION self.db_data_version = CURRENT_DB_DATA_VERSION
self.setIntKV("db_data_version", self.db_data_version, session) self.setIntKV("db_data_version", self.db_data_version, cursor)
session.commit() self.commitDB()
self.log.info( self.log.info(
"Upgraded database records to version {}".format(self.db_data_version) "Upgraded database records to version {}".format(self.db_data_version)
) )
finally: finally:
session.close() self.closeDB(cursor, commit=False)
session.remove()
def upgradeDatabase(self, db_version): def upgradeDatabase(self, db_version):
@ -147,29 +146,27 @@ 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")
) )
cursor.execute("ALTER TABLE transactions ADD COLUMN block_time INTEGER")
db_version += 1 db_version += 1
elif current_version == 8: elif current_version == 8:
session.execute( cursor.execute(
text(
""" """
CREATE TABLE wallets ( CREATE TABLE wallets (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
@ -180,45 +177,39 @@ def upgradeDatabase(self, db_version):
created_at BIGINT, created_at BIGINT,
PRIMARY KEY (record_id))""" PRIMARY KEY (record_id))"""
) )
)
db_version += 1 db_version += 1
elif current_version == 9: elif current_version == 9:
session.execute(text("ALTER TABLE wallets ADD COLUMN wallet_data VARCHAR")) cursor.execute("ALTER TABLE wallets ADD COLUMN wallet_data VARCHAR")
db_version += 1 db_version += 1
elif current_version == 10: elif current_version == 10:
session.execute( cursor.execute(
text("ALTER TABLE smsgaddresses ADD COLUMN active_ind INTEGER") "ALTER TABLE smsgaddresses ADD COLUMN active_ind INTEGER"
) )
session.execute( cursor.execute(
text("ALTER TABLE smsgaddresses ADD COLUMN created_at INTEGER") "ALTER TABLE smsgaddresses ADD COLUMN created_at INTEGER"
) )
session.execute(text("ALTER TABLE smsgaddresses ADD COLUMN note VARCHAR")) cursor.execute("ALTER TABLE smsgaddresses ADD COLUMN note VARCHAR")
session.execute(text("ALTER TABLE smsgaddresses ADD COLUMN pubkey VARCHAR")) cursor.execute("ALTER TABLE smsgaddresses ADD COLUMN pubkey VARCHAR")
session.execute( cursor.execute(
text("UPDATE smsgaddresses SET active_ind = 1, created_at = 1") "UPDATE smsgaddresses SET active_ind = 1, created_at = 1"
) )
session.execute(text("ALTER TABLE offers ADD COLUMN addr_to VARCHAR")) cursor.execute("ALTER TABLE offers ADD COLUMN addr_to VARCHAR")
session.execute(text(f'UPDATE offers SET addr_to = "{self.network_addr}"')) cursor.execute(f'UPDATE offers SET addr_to = "{self.network_addr}"')
db_version += 1 db_version += 1
elif current_version == 11: elif current_version == 11:
session.execute( cursor.execute(
text("ALTER TABLE bids ADD COLUMN chain_a_height_start INTEGER") "ALTER TABLE bids ADD COLUMN chain_a_height_start INTEGER"
) )
session.execute( cursor.execute(
text("ALTER TABLE bids ADD COLUMN chain_b_height_start INTEGER") "ALTER TABLE bids ADD COLUMN chain_b_height_start INTEGER"
) )
session.execute( cursor.execute("ALTER TABLE bids ADD COLUMN protocol_version INTEGER")
text("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")
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 db_version += 1
elif current_version == 12: elif current_version == 12:
session.execute( cursor.execute(
text(
""" """
CREATE TABLE knownidentities ( CREATE TABLE knownidentities (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
@ -236,20 +227,16 @@ def upgradeDatabase(self, db_version):
created_at BIGINT, created_at BIGINT,
PRIMARY KEY (record_id))""" PRIMARY KEY (record_id))"""
) )
cursor.execute("ALTER TABLE bids ADD COLUMN reject_code INTEGER")
cursor.execute("ALTER TABLE bids ADD COLUMN rate INTEGER")
cursor.execute(
"ALTER TABLE offers ADD COLUMN amount_negotiable INTEGER"
) )
session.execute(text("ALTER TABLE bids ADD COLUMN reject_code INTEGER")) cursor.execute("ALTER TABLE offers ADD COLUMN rate_negotiable INTEGER")
session.execute(text("ALTER TABLE bids ADD COLUMN rate INTEGER"))
session.execute(
text("ALTER TABLE offers ADD COLUMN amount_negotiable INTEGER")
)
session.execute(
text("ALTER TABLE offers ADD COLUMN rate_negotiable INTEGER")
)
db_version += 1 db_version += 1
elif current_version == 13: elif current_version == 13:
db_version += 1 db_version += 1
session.execute( cursor.execute(
text(
""" """
CREATE TABLE automationstrategies ( CREATE TABLE automationstrategies (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
@ -264,10 +251,8 @@ def upgradeDatabase(self, db_version):
created_at BIGINT, created_at BIGINT,
PRIMARY KEY (record_id))""" PRIMARY KEY (record_id))"""
) )
)
session.execute( cursor.execute(
text(
""" """
CREATE TABLE automationlinks ( CREATE TABLE automationlinks (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
@ -285,10 +270,8 @@ def upgradeDatabase(self, db_version):
created_at BIGINT, created_at BIGINT,
PRIMARY KEY (record_id))""" PRIMARY KEY (record_id))"""
) )
)
session.execute( cursor.execute(
text(
""" """
CREATE TABLE history ( CREATE TABLE history (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
@ -300,10 +283,8 @@ def upgradeDatabase(self, db_version):
created_at BIGINT, created_at BIGINT,
PRIMARY KEY (record_id))""" PRIMARY KEY (record_id))"""
) )
)
session.execute( cursor.execute(
text(
""" """
CREATE TABLE bidstates ( CREATE TABLE bidstates (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
@ -316,36 +297,32 @@ def upgradeDatabase(self, db_version):
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("ALTER TABLE wallets ADD COLUMN active_ind INTEGER")
session.execute( cursor.execute(
text("ALTER TABLE knownidentities ADD COLUMN active_ind INTEGER") "ALTER TABLE knownidentities ADD COLUMN active_ind INTEGER"
) )
session.execute(text("ALTER TABLE eventqueue RENAME TO actions")) cursor.execute("ALTER TABLE eventqueue RENAME TO actions")
session.execute( cursor.execute(
text("ALTER TABLE actions RENAME COLUMN event_id TO action_id") "ALTER TABLE actions RENAME COLUMN event_id TO action_id"
) )
session.execute( cursor.execute(
text("ALTER TABLE actions RENAME COLUMN event_type TO action_type") "ALTER TABLE actions RENAME COLUMN event_type TO action_type"
) )
session.execute( cursor.execute(
text("ALTER TABLE actions RENAME COLUMN event_data TO action_data") "ALTER TABLE actions RENAME COLUMN event_data TO action_data"
) )
elif current_version == 14: elif current_version == 14:
db_version += 1 db_version += 1
session.execute( cursor.execute(
text("ALTER TABLE xmr_swaps ADD COLUMN coin_a_lock_release_msg_id BLOB") "ALTER TABLE xmr_swaps ADD COLUMN coin_a_lock_release_msg_id BLOB"
) )
session.execute( cursor.execute(
text(
"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
session.execute( cursor.execute(
text(
""" """
CREATE TABLE notifications ( CREATE TABLE notifications (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
@ -355,11 +332,9 @@ def upgradeDatabase(self, db_version):
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
session.execute( cursor.execute(
text(
""" """
CREATE TABLE prefunded_transactions ( CREATE TABLE prefunded_transactions (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
@ -372,40 +347,28 @@ def upgradeDatabase(self, db_version):
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
session.execute( cursor.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
session.execute( cursor.execute("ALTER TABLE xmr_split_data ADD COLUMN addr_from STRING")
text("ALTER TABLE xmr_split_data ADD COLUMN addr_from STRING") cursor.execute("ALTER TABLE xmr_split_data ADD COLUMN addr_to STRING")
)
session.execute(
text("ALTER TABLE xmr_split_data ADD COLUMN addr_to STRING")
)
elif current_version == 19: elif current_version == 19:
db_version += 1 db_version += 1
session.execute(text("ALTER TABLE bidstates ADD COLUMN in_error INTEGER")) cursor.execute("ALTER TABLE bidstates ADD COLUMN in_error INTEGER")
session.execute( cursor.execute("ALTER TABLE bidstates ADD COLUMN swap_failed INTEGER")
text("ALTER TABLE bidstates ADD COLUMN swap_failed INTEGER") cursor.execute("ALTER TABLE bidstates ADD COLUMN swap_ended INTEGER")
)
session.execute(text("ALTER TABLE bidstates ADD COLUMN swap_ended INTEGER"))
elif current_version == 20: elif current_version == 20:
db_version += 1 db_version += 1
session.execute( cursor.execute(
text(
""" """
CREATE TABLE message_links ( CREATE TABLE message_links (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
@ -420,19 +383,17 @@ def upgradeDatabase(self, db_version):
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
session.execute(text("ALTER TABLE offers ADD COLUMN proof_utxos BLOB")) cursor.execute("ALTER TABLE offers ADD COLUMN proof_utxos BLOB")
session.execute(text("ALTER TABLE bids ADD COLUMN proof_utxos BLOB")) cursor.execute("ALTER TABLE bids ADD COLUMN proof_utxos BLOB")
elif current_version == 22: elif current_version == 22:
db_version += 1 db_version += 1
session.execute(text("ALTER TABLE offers ADD COLUMN amount_to INTEGER")) cursor.execute("ALTER TABLE offers ADD COLUMN amount_to INTEGER")
elif current_version == 23: elif current_version == 23:
db_version += 1 db_version += 1
session.execute( cursor.execute(
text(
""" """
CREATE TABLE checkedblocks ( CREATE TABLE checkedblocks (
record_id INTEGER NOT NULL, record_id INTEGER NOT NULL,
@ -443,16 +404,18 @@ def upgradeDatabase(self, db_version):
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, session) self.setIntKV("db_version", db_version, cursor)
session.commit() cursor = self.commitDB()
session.close()
session.remove()
self.log.info("Upgraded database to version {}".format(self.db_version)) self.log.info("Upgraded database to version {}".format(self.db_version))
continue continue
except Exception as e:
self.log.error("Upgrade failed {}".format(e))
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