Use max length fifo queue as temporary solution for offer revoke requests.

2024-05-20_merge
tecnovert 4 years ago
parent 49705f0974
commit e70477eb64
No known key found for this signature in database
GPG Key ID: 8ED6D8750C4E3F93
  1. 33
      basicswap/basicswap.py
  2. 1
      basicswap/messages.proto

@ -18,6 +18,7 @@ import hashlib
import datetime as dt import datetime as dt
import traceback import traceback
import sqlalchemy as sa import sqlalchemy as sa
import collections
from enum import IntEnum, auto from enum import IntEnum, auto
from sqlalchemy.orm import sessionmaker, scoped_session from sqlalchemy.orm import sessionmaker, scoped_session
@ -416,6 +417,7 @@ class BasicSwap(BaseApp):
self._last_checked_expired = 0 self._last_checked_expired = 0
self._last_checked_events = 0 self._last_checked_events = 0
self._last_checked_xmr_swaps = 0 self._last_checked_xmr_swaps = 0
self._possibly_revoked_offers = collections.deque([], maxlen=48) # TODO: improve
# TODO: Adjust ranges # TODO: Adjust ranges
self.min_delay_event = self.settings.get('min_delay_event', 10) self.min_delay_event = self.settings.get('min_delay_event', 10)
@ -3256,6 +3258,9 @@ class BasicSwap(BaseApp):
offer_id = bytes.fromhex(msg['msgid']) offer_id = bytes.fromhex(msg['msgid'])
if self.isOfferRevoked(offer_id, msg['from']):
raise ValueError('Offer has been revoked {}.'.format(offer_id.hex()))
session = scoped_session(self.session_factory) session = scoped_session(self.session_factory)
# Check for sent # Check for sent
existing_offer = self.getOffer(offer_id) existing_offer = self.getOffer(offer_id)
@ -3316,19 +3321,17 @@ class BasicSwap(BaseApp):
if len(msg_data.offer_msg_id) != 28: if len(msg_data.offer_msg_id) != 28:
raise ValueError('Invalid msg_id length') raise ValueError('Invalid msg_id length')
if len(msg_data.signature) != 65:
# TODO: Add to db in case received out of order, or add extra startup logic raise ValueError('Invalid signature length')
offer = session.query(Offer).filter_by(offer_id=msg_data.offer_msg_id).first() offer = session.query(Offer).filter_by(offer_id=msg_data.offer_msg_id).first()
if offer is None: if offer is None:
self.storeOfferRevoke(msg_data.offer_msg_id, msg_data.signature)
raise ValueError('Offer not found: {}'.format(msg_data.offer_msg_id.hex())) raise ValueError('Offer not found: {}'.format(msg_data.offer_msg_id.hex()))
if offer.expire_at <= now: if offer.expire_at <= now:
raise ValueError('Offer already expired: {}'.format(msg_data.offer_msg_id.hex())) raise ValueError('Offer already expired: {}'.format(msg_data.offer_msg_id.hex()))
if len(msg_data.signature) != 65:
raise ValueError('Invalid signature length')
signature_enc = base64.b64encode(msg_data.signature).decode('utf-8') signature_enc = base64.b64encode(msg_data.signature).decode('utf-8')
passed = self.callcoinrpc(Coins.PART, 'verifymessage', [offer.addr_from, signature_enc, msg_data.offer_msg_id.hex() + '_revoke']) passed = self.callcoinrpc(Coins.PART, 'verifymessage', [offer.addr_from, signature_enc, msg_data.offer_msg_id.hex() + '_revoke'])
@ -3366,7 +3369,7 @@ class BasicSwap(BaseApp):
assert(bid_data.amount >= offer.min_bid_amount), 'Bid amount below minimum' assert(bid_data.amount >= offer.min_bid_amount), 'Bid amount below minimum'
assert(now <= msg['sent'] + bid_data.time_valid), 'Bid expired' assert(now <= msg['sent'] + bid_data.time_valid), 'Bid expired'
# TODO: allow higher bids # TODO: Allow higher bids
# assert(bid_data.rate != offer['data'].rate), 'Bid rate mismatch' # assert(bid_data.rate != offer['data'].rate), 'Bid rate mismatch'
coin_to = Coins(offer.coin_to) coin_to = Coins(offer.coin_to)
@ -3623,6 +3626,8 @@ class BasicSwap(BaseApp):
ci_to = self.ci(Coins(offer.coin_to)) ci_to = self.ci(Coins(offer.coin_to))
logging.debug('TODO: xmr bid validation') logging.debug('TODO: xmr bid validation')
assert(ci_to.verifyKey(bid_data.kbvf))
assert(ci_from.verifyPubkey(bid_data.pkaf))
bid_id = bytes.fromhex(msg['msgid']) bid_id = bytes.fromhex(msg['msgid'])
@ -4649,3 +4654,19 @@ class BasicSwap(BaseApp):
bid = self.getBid(bid_id) bid = self.getBid(bid_id)
bid.debug_ind = debug_ind bid.debug_ind = debug_ind
self.saveBid(bid_id, bid) self.saveBid(bid_id, bid)
def storeOfferRevoke(self, offer_id, sig):
self.log.debug('Storing revoke request for offer: %s', offer_id.hex())
for pair in self._possibly_revoked_offers:
if offer_id == pair[0]:
return False
self._possibly_revoked_offers.appendleft((offer_id, sig))
return True
def isOfferRevoked(self, offer_id, offer_addr_from):
for pair in self._possibly_revoked_offers:
if offer_id == pair[0]:
signature_enc = base64.b64encode(pair[1]).decode('utf-8')
passed = self.callcoinrpc(Coins.PART, 'verifymessage', [offer_addr_from, signature_enc, offer_id.hex() + '_revoke'])
return True if passed is True else False # _possibly_revoked_offers should not contain duplicates
return False

@ -55,7 +55,6 @@ message OfferRevokeMessage {
bytes signature = 2; bytes signature = 2;
} }
message XmrBidMessage { message XmrBidMessage {
/* MSG1L, F -> L */ /* MSG1L, F -> L */
bytes offer_msg_id = 1; bytes offer_msg_id = 1;

Loading…
Cancel
Save