refactor: Add bid states to db.

This commit is contained in:
tecnovert 2022-06-11 23:13:12 +02:00
parent 89c60851ac
commit 0edcf249aa
No known key found for this signature in database
GPG Key ID: 8ED6D8750C4E3F93
6 changed files with 109 additions and 75 deletions

View File

@ -3545,10 +3545,6 @@ class BasicSwap(BaseApp):
q = session.query(Action).filter(sa.and_(Action.active_ind == 1, Action.linked_id == bid_id, Action.action_type == int(action_type))) q = session.query(Action).filter(sa.and_(Action.active_ind == 1, Action.linked_id == bid_id, Action.action_type == int(action_type)))
return q.count() return q.count()
def countQueuedAcceptActions(self, session, bid_id):
q = session.query(Action).filter(sa.and_(Action.active_ind == 1, Action.linked_id == bid_id, sa.or_(Action.action_type == int(ActionTypes.ACCEPT_XMR_BID), Action.action_type == int(ActionTypes.ACCEPT_BID))))
return q.count()
def checkQueuedActions(self): def checkQueuedActions(self):
self.mxDB.acquire() self.mxDB.acquire()
now = int(time.time()) now = int(time.time())
@ -3798,25 +3794,19 @@ class BasicSwap(BaseApp):
def getCompletedAndActiveBidsValue(self, offer, session): def getCompletedAndActiveBidsValue(self, offer, session):
bids = [] bids = []
total_value = 0 total_value = 0
q = session.execute('SELECT bid_id, amount, state FROM bids WHERE active_ind = 1 AND offer_id = x\'{}\''.format(offer.offer_id.hex())) q = session.execute(
'''SELECT bid_id, amount, state FROM bids
JOIN bidstates ON bidstates.state_id = bids.state AND (bidstates.state_id = {1} OR bidstates.in_progress > 0)
WHERE bids.active_ind = 1 AND bids.offer_id = x\'{0}\'
UNION
SELECT bid_id, amount, state FROM bids
JOIN actions ON actions.linked_id = bids.bid_id AND actions.active_ind = 1 AND (actions.action_type = {2} OR actions.action_type = {3})
WHERE bids.active_ind = 1 AND bids.offer_id = x\'{0}\'
'''.format(offer.offer_id.hex(), BidStates.SWAP_COMPLETED, ActionTypes.ACCEPT_XMR_BID, ActionTypes.ACCEPT_BID))
for row in q: for row in q:
bid_id, amount, state = row bid_id, amount, state = row
if state == BidStates.SWAP_COMPLETED: bids.append((bid_id, amount, state))
bids.append((bid_id, amount, state, 1))
total_value += amount total_value += amount
continue
if state == BidStates.BID_ACCEPTED:
bids.append((bid_id, amount, state, 2))
total_value += amount
continue
if bid_id in self.swaps_in_progress:
bids.append((bid_id, amount, state, 3))
total_value += amount
continue
if self.countQueuedAcceptActions(session, bid_id) > 0:
bids.append((bid_id, amount, state, 4))
total_value += amount
continue
return bids, total_value return bids, total_value
def shouldAutoAcceptBid(self, offer, bid, session=None): def shouldAutoAcceptBid(self, offer, bid, session=None):
@ -3855,7 +3845,7 @@ class BasicSwap(BaseApp):
num_not_completed = 0 num_not_completed = 0
for active_bid in active_bids: for active_bid in active_bids:
if active_bid[3] != 1: if active_bid[2] != BidStates.SWAP_COMPLETED:
num_not_completed += 1 num_not_completed += 1
max_concurrent_bids = opts.get('max_concurrent_bids', 1) max_concurrent_bids = opts.get('max_concurrent_bids', 1)
if num_not_completed >= max_concurrent_bids: if num_not_completed >= max_concurrent_bids:
@ -5062,12 +5052,6 @@ class BasicSwap(BaseApp):
session = scoped_session(self.session_factory) session = scoped_session(self.session_factory)
try: try:
activate_bid = False activate_bid = False
if offer.swap_type == SwapTypes.SELLER_FIRST:
if bid.state and bid.state > BidStates.BID_RECEIVED and bid.state < BidStates.SWAP_COMPLETED:
activate_bid = True
else:
self.log.debug('TODO - determine in-progress for manualBidUpdate')
if offer.swap_type == SwapTypes.XMR_SWAP:
if bid.state and isActiveBidState(bid.state): if bid.state and isActiveBidState(bid.state):
activate_bid = True activate_bid = True

View File

@ -64,38 +64,38 @@ class SwapTypes(IntEnum):
class OfferStates(IntEnum): class OfferStates(IntEnum):
OFFER_SENT = auto() OFFER_SENT = 1
OFFER_RECEIVED = auto() OFFER_RECEIVED = 2
OFFER_ABANDONED = auto() OFFER_ABANDONED = 3
class BidStates(IntEnum): class BidStates(IntEnum):
BID_SENT = auto() BID_SENT = 1
BID_RECEIVING = auto() # Partially received BID_RECEIVING = 2 # Partially received
BID_RECEIVED = auto() BID_RECEIVED = 3
BID_RECEIVING_ACC = auto() # Partially received accept message BID_RECEIVING_ACC = 4 # Partially received accept message
BID_ACCEPTED = auto() # BidAcceptMessage received/sent BID_ACCEPTED = 5 # BidAcceptMessage received/sent
SWAP_INITIATED = auto() # Initiate txn validated SWAP_INITIATED = 6 # Initiate txn validated
SWAP_PARTICIPATING = auto() # Participate txn validated SWAP_PARTICIPATING = 7 # Participate txn validated
SWAP_COMPLETED = auto() # All swap txns spent SWAP_COMPLETED = 8 # All swap txns spent
XMR_SWAP_SCRIPT_COIN_LOCKED = auto() XMR_SWAP_SCRIPT_COIN_LOCKED = 9
XMR_SWAP_HAVE_SCRIPT_COIN_SPEND_TX = auto() XMR_SWAP_HAVE_SCRIPT_COIN_SPEND_TX = 10
XMR_SWAP_NOSCRIPT_COIN_LOCKED = auto() XMR_SWAP_NOSCRIPT_COIN_LOCKED = 11
XMR_SWAP_LOCK_RELEASED = auto() XMR_SWAP_LOCK_RELEASED = 12
XMR_SWAP_SCRIPT_TX_REDEEMED = auto() XMR_SWAP_SCRIPT_TX_REDEEMED = 13
XMR_SWAP_SCRIPT_TX_PREREFUND = auto() # script txo moved into pre-refund tx XMR_SWAP_SCRIPT_TX_PREREFUND = 14 # script txo moved into pre-refund tx
XMR_SWAP_NOSCRIPT_TX_REDEEMED = auto() XMR_SWAP_NOSCRIPT_TX_REDEEMED = 15
XMR_SWAP_NOSCRIPT_TX_RECOVERED = auto() XMR_SWAP_NOSCRIPT_TX_RECOVERED = 16
XMR_SWAP_FAILED_REFUNDED = auto() XMR_SWAP_FAILED_REFUNDED = 17
XMR_SWAP_FAILED_SWIPED = auto() XMR_SWAP_FAILED_SWIPED = 18
XMR_SWAP_FAILED = auto() XMR_SWAP_FAILED = 19
SWAP_DELAYING = auto() SWAP_DELAYING = 20
SWAP_TIMEDOUT = auto() SWAP_TIMEDOUT = 21
BID_ABANDONED = auto() # Bid will no longer be processed BID_ABANDONED = 22 # Bid will no longer be processed
BID_ERROR = auto() # An error occurred BID_ERROR = 23 # An error occurred
BID_STALLED_FOR_TEST = auto() BID_STALLED_FOR_TEST = 24
BID_REJECTED = auto() BID_REJECTED = 25
BID_STATE_UNKNOWN = auto() BID_STATE_UNKNOWN = 26
class TxStates(IntEnum): class TxStates(IntEnum):
@ -385,6 +385,10 @@ def getLastBidState(packed_states):
def isActiveBidState(state): def isActiveBidState(state):
if state >= BidStates.BID_ACCEPTED and state < BidStates.SWAP_COMPLETED:
return True
if state == BidStates.SWAP_DELAYING:
return True
if state == BidStates.XMR_SWAP_HAVE_SCRIPT_COIN_SPEND_TX: if state == BidStates.XMR_SWAP_HAVE_SCRIPT_COIN_SPEND_TX:
return True return True
if state == BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED: if state == BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED:

View File

@ -460,3 +460,16 @@ class History(Base):
changed_data = sa.Column(sa.LargeBinary) changed_data = sa.Column(sa.LargeBinary)
created_at = sa.Column(sa.BigInteger) created_at = sa.Column(sa.BigInteger)
class BidState(Base):
__tablename__ = 'bidstates'
record_id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
active_ind = sa.Column(sa.Integer)
state_id = sa.Column(sa.Integer)
label = sa.Column(sa.String)
in_progress = sa.Column(sa.Integer)
note = sa.Column(sa.String)
created_at = sa.Column(sa.BigInteger)

View File

@ -5,14 +5,21 @@
# 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
from sqlalchemy.orm import scoped_session from sqlalchemy.orm import scoped_session
from .db import ( from .db import (
BidState,
Concepts, Concepts,
AutomationStrategy, AutomationStrategy,
CURRENT_DB_VERSION, CURRENT_DB_VERSION,
CURRENT_DB_DATA_VERSION) CURRENT_DB_DATA_VERSION)
from .basicswap_util import (
BidStates,
strBidState,
isActiveBidState)
def upgradeDatabaseData(self, data_version): def upgradeDatabaseData(self, data_version):
if data_version >= CURRENT_DB_DATA_VERSION: if data_version >= CURRENT_DB_DATA_VERSION:
@ -23,6 +30,8 @@ def upgradeDatabaseData(self, data_version):
try: try:
session = scoped_session(self.session_factory) session = scoped_session(self.session_factory)
now = int(time.time())
if data_version < 1: if data_version < 1:
session.add(AutomationStrategy( session.add(AutomationStrategy(
active_ind=1, active_ind=1,
@ -30,7 +39,8 @@ def upgradeDatabaseData(self, data_version):
type_ind=Concepts.OFFER, type_ind=Concepts.OFFER,
data=json.dumps({'exact_rate_only': True, data=json.dumps({'exact_rate_only': True,
'max_concurrent_bids': 5}).encode('utf-8'), 'max_concurrent_bids': 5}).encode('utf-8'),
only_known_identities=False)) only_known_identities=False,
created_at=now))
session.add(AutomationStrategy( session.add(AutomationStrategy(
active_ind=1, active_ind=1,
label='Accept Known', label='Accept Known',
@ -38,7 +48,16 @@ def upgradeDatabaseData(self, data_version):
data=json.dumps({'exact_rate_only': True, data=json.dumps({'exact_rate_only': True,
'max_concurrent_bids': 5}).encode('utf-8'), 'max_concurrent_bids': 5}).encode('utf-8'),
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))
for state in BidStates:
session.add(BidState(
active_ind=1,
state_id=int(state),
in_progress=isActiveBidState(state),
label=strBidState(state),
created_at=now))
self.db_data_version = CURRENT_DB_DATA_VERSION self.db_data_version = CURRENT_DB_DATA_VERSION
self.setIntKVInSession('db_data_version', self.db_data_version, session) self.setIntKVInSession('db_data_version', self.db_data_version, session)
@ -166,6 +185,17 @@ def upgradeDatabase(self, db_version):
created_at BIGINT, created_at BIGINT,
PRIMARY KEY (record_id))''') PRIMARY KEY (record_id))''')
session.execute('''
CREATE TABLE bidstates (
record_id INTEGER NOT NULL,
state_id INTEGER,
label VARCHAR,
in_progress INTEGER,
note VARCHAR,
created_at BIGINT,
PRIMARY KEY (record_id))''')
session.execute('ALTER TABLE wallets ADD COLUMN active_ind INTEGER') session.execute('ALTER TABLE wallets ADD COLUMN active_ind INTEGER')
session.execute('ALTER TABLE knownidentities ADD COLUMN active_ind INTEGER') session.execute('ALTER TABLE knownidentities ADD COLUMN active_ind INTEGER')
session.execute('ALTER TABLE eventqueue RENAME TO actions') session.execute('ALTER TABLE eventqueue RENAME TO actions')

View File

@ -5,7 +5,7 @@
# 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 time import json
import logging import logging
import basicswap.contrib.ed25519_fast as edf import basicswap.contrib.ed25519_fast as edf
@ -217,7 +217,7 @@ class XMRInterface(CoinInterface):
def encodeSharedAddress(self, Kbv, Kbs): def encodeSharedAddress(self, Kbv, Kbs):
return xmr_util.encode_address(Kbv, Kbs) return xmr_util.encode_address(Kbv, Kbs)
def publishBLockTx(self, Kbv, Kbs, output_amount, feerate): def publishBLockTx(self, Kbv, Kbs, output_amount, feerate, delay_for=10):
with self._mx_wallet: with self._mx_wallet:
self.rpc_wallet_cb('open_wallet', {'filename': self._wallet_filename}) self.rpc_wallet_cb('open_wallet', {'filename': self._wallet_filename})
@ -230,14 +230,17 @@ class XMRInterface(CoinInterface):
self._log.info('publishBLockTx %s to address_b58 %s', rv['tx_hash'], shared_addr) self._log.info('publishBLockTx %s to address_b58 %s', rv['tx_hash'], shared_addr)
tx_hash = bytes.fromhex(rv['tx_hash']) tx_hash = bytes.fromhex(rv['tx_hash'])
# Debug if self._sc.debug:
for i in range(10): i = 0
while not self._sc.delay_event.is_set():
params = {'out': True, 'pending': True, 'failed': True, 'pool': True, } params = {'out': True, 'pending': True, 'failed': True, 'pool': True, }
rv = self.rpc_wallet_cb('get_transfers', params) rv = self.rpc_wallet_cb('get_transfers', params)
self._log.info('[rm] get_transfers {}'.format(dumpj(rv))) self._log.debug('get_transfers {}'.format(dumpj(rv)))
if 'pending' not in rv: if 'pending' not in rv:
break break
time.sleep(1) if i >= delay_for:
break
self._sc.delay_event.wait(1.0)
return tx_hash return tx_hash
@ -333,7 +336,6 @@ class XMRInterface(CoinInterface):
return True return True
# TODO: Is it necessary to check the address? # TODO: Is it necessary to check the address?
''' '''
rv = self.rpc_wallet_cb('get_balance') rv = self.rpc_wallet_cb('get_balance')
print('get_balance', rv) print('get_balance', rv)
@ -346,7 +348,9 @@ class XMRInterface(CoinInterface):
if i >= num_tries: if i >= num_tries:
raise ValueError('Balance not confirming on node') raise ValueError('Balance not confirming on node')
time.sleep(1) self._sc.delay_event.wait(1.0)
if self._sc.delay_event.is_set():
raise ValueError('Stopped')
return False return False
@ -431,7 +435,7 @@ class XMRInterface(CoinInterface):
params['priority'] = self._fee_priority params['priority'] = self._fee_priority
rv = self.rpc_wallet_cb('sweep_all', params) rv = self.rpc_wallet_cb('sweep_all', params)
print('sweep_all', rv) self._log.debug('sweep_all {}'.format(json.dumps(rv)))
return bytes.fromhex(rv['tx_hash_list'][0]) return bytes.fromhex(rv['tx_hash_list'][0])

View File

@ -731,7 +731,6 @@ class Test(BaseTest):
offer = swap_clients[1].getOffer(offer_id) offer = swap_clients[1].getOffer(offer_id)
bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from) bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from)
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED)
bid, xmr_swap = swap_clients[0].getXmrBid(bid_id) bid, xmr_swap = swap_clients[0].getXmrBid(bid_id)