diff --git a/basicswap/__init__.py b/basicswap/__init__.py
index 70dbfc1..af2ffe5 100644
--- a/basicswap/__init__.py
+++ b/basicswap/__init__.py
@@ -1,3 +1,3 @@
name = "basicswap"
-__version__ = "0.11.63"
+__version__ = "0.11.64"
diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py
index bac529b..2f5952e 100644
--- a/basicswap/basicswap.py
+++ b/basicswap/basicswap.py
@@ -2515,7 +2515,7 @@ class BasicSwap(BaseApp):
session.close()
session.remove()
- self.log.info('Sent XMR_BID_FL %s', xmr_swap.bid_id.hex())
+ self.log.info('Sent ADS_BID_LF %s', xmr_swap.bid_id.hex())
return xmr_swap.bid_id
msg_buf = XmrBidMessage()
@@ -4100,15 +4100,14 @@ class BasicSwap(BaseApp):
try:
ci_part = self.ci(Coins.PART)
rpc_conn = ci_part.open_rpc()
- now: int = self.getTime()
- options = {'encoding': 'none'}
- ro = ci_part.json_request(rpc_conn, 'smsginbox', ['all', '', options])
- num_messages = 0
- num_removed = 0
- for msg in ro['messages']:
+ num_messages: int = 0
+ num_removed: int = 0
+
+ def remove_if_expired(msg):
+ nonlocal num_messages, num_removed
try:
num_messages += 1
- expire_at = msg['sent'] + msg['ttl']
+ expire_at: int = msg['sent'] + msg['ttl']
if expire_at < now:
options = {'encoding': 'none', 'delete': True}
del_msg = ci_part.json_request(rpc_conn, 'smsg', [msg['msgid'], options])
@@ -4116,7 +4115,15 @@ class BasicSwap(BaseApp):
except Exception as e:
if self.debug:
self.log.error(traceback.format_exc())
- continue
+
+ now: int = self.getTime()
+ options = {'encoding': 'none'}
+ inbox_messages = ci_part.json_request(rpc_conn, 'smsginbox', ['all', '', options])['messages']
+ for msg in inbox_messages:
+ remove_if_expired(msg)
+ outbox_messages = ci_part.json_request(rpc_conn, 'smsgoutbox', ['all', '', options])['messages']
+ for msg in outbox_messages:
+ remove_if_expired(msg)
if num_messages + num_removed > 0:
self.log.info('Expired {} / {} messages.'.format(num_removed, num_messages))
@@ -4481,15 +4488,23 @@ class BasicSwap(BaseApp):
self.log.debug('Evaluating against strategy {}'.format(strategy.record_id))
if not offer.amount_negotiable:
- if bid.amount != offer.amount_from:
- raise AutomationConstraint('Need exact amount match')
+ if reverse_bid:
+ if abs(bid_amount - offer.amount_from) >= 20: # TODO: Tolerance?
+ raise AutomationConstraint('Need exact amount match')
+ else:
+ if bid_amount != offer.amount_from:
+ raise AutomationConstraint('Need exact amount match')
if bid_amount < offer.min_bid_amount:
raise AutomationConstraint('Bid amount below offer minimum')
if opts.get('exact_rate_only', False) is True:
- if bid_rate != offer.rate:
- raise AutomationConstraint('Need exact rate match')
+ if reverse_bid:
+ if abs(bid_rate - offer.rate) >= 20: # TODO: Tolerance?
+ raise AutomationConstraint('Need exact rate match')
+ else:
+ if bid_rate != offer.rate:
+ raise AutomationConstraint('Need exact rate match')
active_bids, total_bids_value = self.getCompletedAndActiveBidsValue(offer, use_session)
diff --git a/basicswap/static/sequence_diagrams/xmr.bidder.alt.xu.min.svg b/basicswap/static/sequence_diagrams/ads.bidder.alt.xu.min.svg
similarity index 100%
rename from basicswap/static/sequence_diagrams/xmr.bidder.alt.xu.min.svg
rename to basicswap/static/sequence_diagrams/ads.bidder.alt.xu.min.svg
diff --git a/basicswap/static/sequence_diagrams/xmr.offerer.alt.xu.min.svg b/basicswap/static/sequence_diagrams/ads.offerer.alt.xu.min.svg
similarity index 100%
rename from basicswap/static/sequence_diagrams/xmr.offerer.alt.xu.min.svg
rename to basicswap/static/sequence_diagrams/ads.offerer.alt.xu.min.svg
diff --git a/basicswap/static/sequence_diagrams/ads.rev.bidder.xu.min.svg b/basicswap/static/sequence_diagrams/ads.rev.bidder.xu.min.svg
new file mode 100644
index 0000000..42b23d2
--- /dev/null
+++ b/basicswap/static/sequence_diagrams/ads.rev.bidder.xu.min.svg
@@ -0,0 +1,391 @@
+
diff --git a/basicswap/static/sequence_diagrams/ads.rev.offerer.xu.min.svg b/basicswap/static/sequence_diagrams/ads.rev.offerer.xu.min.svg
new file mode 100644
index 0000000..f1b4199
--- /dev/null
+++ b/basicswap/static/sequence_diagrams/ads.rev.offerer.xu.min.svg
@@ -0,0 +1,420 @@
+
diff --git a/basicswap/templates/bid_xmr.html b/basicswap/templates/bid_xmr.html
index ebe093d..0915263 100644
--- a/basicswap/templates/bid_xmr.html
+++ b/basicswap/templates/bid_xmr.html
@@ -639,7 +639,11 @@
-

+ {% if data.reverse_bid %}
+

+ {% else %}
+

+ {% endif %}
@@ -673,7 +677,11 @@
-

+ {% if data.reverse_bid %}
+

+ {% else %}
+

+ {% endif %}
diff --git a/basicswap/ui/util.py b/basicswap/ui/util.py
index 385af83..e109932 100644
--- a/basicswap/ui/util.py
+++ b/basicswap/ui/util.py
@@ -155,8 +155,8 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
ci_leader = ci_to if reverse_bid else ci_from
ci_follower = ci_from if reverse_bid else ci_to
- bid_amount = bid.amount
- bid_rate = offer.rate if bid.rate is None else bid.rate
+ bid_amount: int = bid.amount
+ bid_rate: int = offer.rate if bid.rate is None else bid.rate
if reverse_bid:
bid_amount, bid_rate = reverseBidAmountAndRate(swap_client, bid, offer)
@@ -271,6 +271,7 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
'can_abandon': can_abandon,
'events': bid_events,
'debug_ui': swap_client.debug_ui,
+ 'reverse_bid': reverse_bid,
}
if edit_bid:
diff --git a/doc/protocols/xmr.md b/doc/protocols/adaptor_sig.md
similarity index 81%
rename from doc/protocols/xmr.md
rename to doc/protocols/adaptor_sig.md
index c47e494..431afdc 100644
--- a/doc/protocols/xmr.md
+++ b/doc/protocols/adaptor_sig.md
@@ -1,4 +1,4 @@
-# XMR protocol
+# Adaptor Signature Swap protocol
## WIP
@@ -10,21 +10,24 @@ An OtVES:
- The encrypting private key (b) can be recovered using both the encrypted and decrypted signatures.
-Leader - sends the first lock tx.
+Offerer - Sends the offer
+Bidder - Sends the bid
+Leader - Sends the first lock tx (ITX)
+Follower - Sends the second lock tx (PTX)
NOSCRIPT_COIN lock tx:
- - sent second
- - is sent to a combined key using a private key from each participant.
+ - Sent second.
+ - Is sent to a combined key using a private key from each participant.
SCRIPT_COIN lock tx:
- Sent first
- Requires two signatures to spend from.
- Refund to sender txn is presigned for and can only be mined in the future.
- - Spending the refund tx reveals the leader's NOSCRIPT_COIN split private key
+ - Spending the refund tx reveals the leader's NOSCRIPT_COIN split private key.
- Sender withholds signature until NOSCRIPT_COIN lock tx is confirmed.
- - spending the spend txn reveals the follower's NOSCRIPT_COIN split private key
+ - spending the spend txn reveals the follower's NOSCRIPT_COIN split private key.
```
@@ -32,48 +35,49 @@ Offerer (Leader) | Bidder
------------------------------------------------------------------------|-------------------------------------------------------------------------------|
o1. Sends offer | |
- x SCRIPT_COIN for y NOSCRIPT_COIN | |
- - sends smsg OfferMessage | |
+ - Sends smsg OfferMessage | |
| b1. Receives offer |
- | - validates offer |
+ | - Validates offer |
| b2. Sends bid |
- | - sends smsgs XmrBidMessage + 2x XmrSplitMessage |
+ | - Sends smsgs XmrBidMessage + 2x XmrSplitMessage |
| |
o2. Receives bid | |
- - validates bid | |
+ - Validates bid | |
o3. Accepts bid | |
- - sends smsgs XmrBidAcceptMessage + 2x XmrSplitMessage | |
+ - Sends smsgs XmrBidAcceptMessage + 2x XmrSplitMessage | |
| |
| b3. Receives bid accept |
- | - validates |
- | - signs for lock tx refund |
- | - sends smsg XmrBidLockTxSigsMessage |
+ | - Validates |
+ | - Signs for lock tx refund |
+ | - Sends smsg XmrBidLockTxSigsMessage |
| |
o4. Receives bidder lock refund tx signatures | |
- - sends smsg XmrBidLockSpendTxMessage | |
- - full SCRIPT_COIN lock tx | |
- - signature to prove leader can sign for split key | |
- - submits SCRIPT_COIN lock tx to network | |
+ - Sends smsg XmrBidLockSpendTxMessage | |
+ - Full SCRIPT_COIN lock tx | |
+ - Signature to prove leader can sign for split key | |
+ - Submits SCRIPT_COIN lock tx to network | |
| |
| b4. Receives XmrBidLockSpendTxMessage |
- | - validates SCRIPT_COIN lock tx and signature |
- | - waits for SCRIPT_COIN lock tx to confirm in chain |
+ | - Validates SCRIPT_COIN lock tx and signature |
+ | - Waits for SCRIPT_COIN lock tx to confirm in chain |
| b5. Sends NOSCRIPT_COIN lock tx |
| |
o5. Waits for NOSCRIPT_COIN lock tx to confirm in chain | |
o6. Sends SCRIPT_COIN lock release. | |
- - sends smsg XmrBidLockReleaseMessage | |
- - includes OtVES ciphertext signature for the SCRIPT_COIN lock | |
+ - Sends smsg XmrBidLockReleaseMessage | |
+ - Includes OtVES ciphertext signature for the SCRIPT_COIN lock | |
spend tx. | |
| |
| b6. Receives offerer OtVES for SCRIPT_COIN lock spend tx. |
- | - submits SCRIPT_COIN lock spend tx to network. |
+ | - Submits SCRIPT_COIN lock spend tx to network. |
| |
o7. Waits for SCRIPT_COIN lock spend tx. | |
- Extracts the NOSCRIPT_COIN bidders key using the signature | |
o8. Combines the keys to spend from the NOSCRIPT_COIN lock tx | |
- - submits NOSCRIPT_COIN lock spend tx to network | |
+ - Submits NOSCRIPT_COIN lock spend tx to network | |
```
+Per swap (including the offer smsg):
Offerer sent 6 smsgs (2 extra from split messages)
Bidder sent 4 smsgs (2 extra from split messages)
diff --git a/doc/protocols/adaptor_sig_reversed.md b/doc/protocols/adaptor_sig_reversed.md
new file mode 100644
index 0000000..f323bfb
--- /dev/null
+++ b/doc/protocols/adaptor_sig_reversed.md
@@ -0,0 +1,85 @@
+# Reverse Adaptor Signature Swap protocol
+
+
+
+## WIP
+
+Offerer - Sends the offer
+Bidder - Sends the bid
+Leader - Sends the first lock tx (ITX)
+Follower - Sends the second lock tx (PTX)
+
+
+The ITX must be sent from the script chain (coin A).
+The side sending the ITX can be switched and the system can abstract to
+users that the protocol is running in the opposite direction.
+
+
+NOSCRIPT_COIN lock tx:
+ - Sent second.
+ - Is sent to a combined key using a private key from each participant.
+
+
+SCRIPT_COIN lock tx:
+ - Sent first.
+ - Requires two signatures to spend from.
+ - Refund to sender txn is presigned for and can only be mined in the future.
+ - Spending the refund tx reveals the leader's NOSCRIPT_COIN split private key.
+ - Sender withholds signature until NOSCRIPT_COIN lock tx is confirmed.
+ - spending the spend txn reveals the follower's NOSCRIPT_COIN split private key.
+
+
+```
+Offerer (Follower) | Bidder (Leader) |
+------------------------------------------------------------------------|-------------------------------------------------------------------------------|
+o1. Sends offer | |
+ - x NOSCRIPT_COIN for y SCRIPT_COIN | |
+ - Sends smsg OfferMessage | |
+ | b1. Receives offer |
+ | - Validates offer |
+ | b2. Sends bid intent message |
+ | - Sends smsg ADSBidIntentMessage |
+ | |
+o2. Receives bid intent message | |
+ - Validates bid intent | |
+o3. Accepts bid intent message | |
+ - Sends smsgs ADSBidIntentAcceptMessage + 2x XmrSplitMessage | |
+ | |
+ | b3. Receives bid intent message |
+ | - Sends smsgs XmrBidAcceptMessage + 2x XmrSplitMessage |
+ | |
+o4. Receives bid accept | |
+ - Validates | |
+ - Signs for lock tx refund | |
+ - Sends smsg XmrBidLockTxSigsMessage | |
+ | |
+ | b4. Receives bidder lock refund tx signatures |
+ | - Sends smsg XmrBidLockSpendTxMessage |
+ | - Full SCRIPT_COIN lock tx |
+ | - Signature to prove leader can sign for split key |
+ | - Submits SCRIPT_COIN lock tx to network |
+ | |
+o5. Receives XmrBidLockSpendTxMessage | |
+ - Validates SCRIPT_COIN lock tx and signature | |
+ - Waits for SCRIPT_COIN lock tx to confirm in chain | |
+o6. Sends NOSCRIPT_COIN lock tx | |
+ | |
+ | b5. Waits for NOSCRIPT_COIN lock tx to confirm in chain |
+ | b6. Sends SCRIPT_COIN lock release. |
+ | - Sends smsg XmrBidLockReleaseMessage |
+ | - Includes OtVES ciphertext signature for the SCRIPT_COIN lock |
+ | spend tx. |
+ | |
+o7. Receives leader OtVES for SCRIPT_COIN lock spend tx. | |
+ - Submits SCRIPT_COIN lock spend tx to network. | |
+ | |
+ | b7. Waits for SCRIPT_COIN lock spend tx. |
+ | - Extracts the NOSCRIPT_COIN follower's key using the signature |
+ | b8. Combines the keys to spend from the NOSCRIPT_COIN lock tx |
+ | - Submits NOSCRIPT_COIN lock spend tx to network |
+```
+
+Per swap (including the offer smsg):
+Offerer sent 5 smsgs (2 extra from split messages)
+Bidder sent 6 smsgs (2 extra from split messages)
+
diff --git a/doc/protocols/seller_first.md b/doc/protocols/secret_hash_seller_first.md
similarity index 100%
rename from doc/protocols/seller_first.md
rename to doc/protocols/secret_hash_seller_first.md
diff --git a/doc/protocols/sequence_diagrams/xmr.bidder.alt.xu b/doc/protocols/sequence_diagrams/ads.bidder.alt.xu
similarity index 100%
rename from doc/protocols/sequence_diagrams/xmr.bidder.alt.xu
rename to doc/protocols/sequence_diagrams/ads.bidder.alt.xu
diff --git a/doc/protocols/sequence_diagrams/xmr.offerer.alt.xu b/doc/protocols/sequence_diagrams/ads.offerer.alt.xu
similarity index 100%
rename from doc/protocols/sequence_diagrams/xmr.offerer.alt.xu
rename to doc/protocols/sequence_diagrams/ads.offerer.alt.xu
diff --git a/doc/protocols/sequence_diagrams/ads.rev.bidder.xu b/doc/protocols/sequence_diagrams/ads.rev.bidder.xu
new file mode 100644
index 0000000..28189c8
--- /dev/null
+++ b/doc/protocols/sequence_diagrams/ads.rev.bidder.xu
@@ -0,0 +1,79 @@
+xu {
+ hscale="1.3", wordwraparcs=on;
+
+ CB [label=" ", linecolor="transparent"],
+ N [label="Network", linecolor="#008800", textbgcolor="#CCFFCC", arclinecolor="#008800"],
+ O [label="Offerer", linecolor="#FF0000", textbgcolor="#FFCCCC", arclinecolor="#FF0000"],
+ B [label="Bidder", linecolor="#0000FF", textbgcolor="#CCCCFF", arclinecolor="#0000FF"],
+ C [label=" ", linecolor="transparent"], C2 [label=" ", linecolor="transparent"];
+ O =>> N [label="Sends Offer"];
+ N >> B [label="Detects Offer"];
+ B =>> O [label="Sends BidIntent message"];
+ B abox B [label="Bid Request sent"];
+ O box O [label="User accepts bid"];
+ O =>> B [label="Sends BidIntentAccept message"],
+ C note C2
+ [label="The BidAccept message contains the pubkeys the offerer will use and a DLEAG proof one key will work across both chains of the swapping coins",
+ textbgcolor="#FFFFCC"];
+ B abox B [label="Bid Receiving accept"];
+ B =>> O [label="Sends BidAccept message"];
+ B abox B [label="Bid Accepted"];
+
+ O =>> B [label="Sends XmrBidLockTxSigsMessage"],
+ C note C2
+ [label="The XmrBidLockTxSigsMessage contains the offerer's signatures for the script-coin-lock-refund and script-coin-lock-refund-spend txns.",
+ textbgcolor="#FFFFCC"];
+ B abox B [label="Exchanged script lock tx sigs msg"];
+ B =>> N [label="Sends script-coin-lock-tx"];
+ B abox B [label="Bid Script coin spend tx valid"];
+ B =>> O [label="Sends XmrBidLockSpendTxMessage"],
+ C note C2
+ [label="The XmrBidLockSpendTxMessage contains the script-coin-lock-tx and proof the bidder can sign it.",
+ textbgcolor="#FFFFCC"];
+ B abox B [label="Exchanged script lock spend tx msg"];
+
+ |||;
+ O => O [label="Wait for script-coin-lock-tx to confirm"], B => B [label="Wait for script-coin-lock-tx to confirm"];
+ B abox B [label="Bid Script coin locked"];
+ CB alt C [label="success path"] {
+ O =>> N [label="Sends noscript-coin-lock-tx"];
+ |||;
+ B => B [label="Wait for noscript-coin-lock-tx to confirm"];
+ B abox B [label="Bid Scriptless coin locked"];
+ B => O [label="Sends script-coin-lock-tx release message"],
+ C note C2
+ [label="The XmrBidLockReleaseMessage contains the bidder's OTVES for the script-coin-lock-tx.
+ The offerer decodes the bidder's signature from the OTVES.
+ When the bidder has the plaintext signature, they can decode the offerer's key for the noscript-lock-tx.",
+ textbgcolor="#FFFFCC"];
+ B abox B [label="Bid Script coin lock released"];
+ O =>> N [label="Sends script-coin-lock-spend-tx"];
+ N >> B [label="Detects script-coin-lock-spend-tx"];
+ B abox B [label="Bid Script tx redeemed"],
+ C note C2
+ [label="The bidder extracts the offerer's plaintext signature and derives the offerer's noscript-lock-tx keyhalf.",
+ textbgcolor="#FFFFCC"];
+ B =>> N [label="Sends noscript-coin-lock-spend-tx"];
+ B abox B [label="Bid Scriptless tx redeemed"];
+ |||;
+ B => B [label="Wait for noscript-coin-lock-spend-tx to confirm"];
+ B abox B [label="Bid Completed"];
+ --- [label="fail path"];
+ |||;
+ B => B [label="Wait for script-coin-lock-tx locktime to expire"];
+ B =>> N [label="Sends script-coin-lock-pre-refund-tx"],
+ C note C2
+ [label="tx can be sent by either party.",
+ textbgcolor="#FFFFCC"];
+ N >> B [label="script-coin-lock-pre-refund-tx"];
+ B abox B [label="Bid Script pre-refund tx in chain"];
+ |||;
+ B => B [label="Wait for pre-refund tx to confirm"];
+ B =>> N [label="Sends script-coin-lock-pre-refund-spend-tx"],
+ C note C2
+ [label="Refunds the script lock tx, with the bidder's cleartext signature the offerer can refund the noscript lock tx.",
+ textbgcolor="#FFFFCC"];
+ B abox B [label="Bid Failed, refunded"];
+ };
+}
+
diff --git a/doc/protocols/sequence_diagrams/ads.rev.offerer.xu b/doc/protocols/sequence_diagrams/ads.rev.offerer.xu
new file mode 100644
index 0000000..7c919de
--- /dev/null
+++ b/doc/protocols/sequence_diagrams/ads.rev.offerer.xu
@@ -0,0 +1,86 @@
+xu {
+ hscale="1.3", wordwraparcs=on;
+
+ CB [label=" ", linecolor="transparent"],
+ N [label="Network", linecolor="#008800", textbgcolor="#CCFFCC", arclinecolor="#008800"],
+ O [label="Offerer", linecolor="#FF0000", textbgcolor="#FFCCCC", arclinecolor="#FF0000"],
+ B [label="Bidder", linecolor="#0000FF", textbgcolor="#CCCCFF", arclinecolor="#0000FF"],
+ C [label=" ", linecolor="transparent"], C2 [label=" ", linecolor="transparent"];
+ O =>> N [label="Sends Offer"];
+ N >> B [label="Detects Offer"];
+ B =>> O [label="Sends BidIntent message"];
+ O abox O [label="Bid Received"];
+ O box O [label="User accepts bid"];
+ O =>> B [label="Sends BidIntentAccept message"],
+ C note C2
+ [label="The BidAccept message contains the pubkeys the offerer will use and a DLEAG proof one key will work across both chains of the swapping coins",
+ textbgcolor="#FFFFCC"];
+ B =>> O [label="Sends BidAccept message"],
+ C note C2
+ [label="The BidAccept message contains the pubkeys the bidder will use and a DLEAG proof one key will work across both chains of the swapping coins",
+ textbgcolor="#FFFFCC"];
+ O abox O [label="Bid Accepted"];
+
+
+ O =>> B [label="Sends XmrBidLockTxSigsMessage"],
+ C note C2
+ [label="The XmrBidLockTxSigsMessage contains the offerer's signatures for the script-coin-lock-refund and script-coin-lock-refund-spend txns.",
+ textbgcolor="#FFFFCC"];
+ O abox O [label="Exchanged script lock tx sigs msg"];
+ B =>> O [label="Sends XmrBidLockSpendTxMessage"],
+ C note C2
+ [label="The XmrBidLockSpendTxMessage contains the script-coin-lock-tx and proof the bidder can sign it.",
+ textbgcolor="#FFFFCC"];
+ B =>> N [label="Sends script-coin-lock-tx"],
+ O abox O [label="Bid Script coin spend tx valid"];
+ O abox O [label="Exchanged script lock spend tx msg"];
+ O => O [label="Wait for script-coin-lock-tx to confirm"];
+ O abox O [label="Bid Script coin locked"];
+ # offerer would only send noscript-coin-lock-tx if script-coin-lock-tx validates
+ O =>> N [label="Sends noscript-coin-lock-tx"];
+ O => O [label="Wait for noscript-coin-lock-tx to confirm"], B => B [label="Wait for noscript-coin-lock-tx to confirm"];
+ O abox O [label="Bid Scriptless coin locked"];
+ CB alt C [label="success path"] {
+ B => O [label="Sends script-coin-lock-tx release message"],
+ C note C2
+ [label="The XmrBidLockReleaseMessage contains the bidder's OTVES for it.
+ The offerer decodes the bidder's signature from the OTVES.
+ When the bidder has the plaintext signature, they can decode the offerer's noscript-coin-lock-tx signature.",
+ textbgcolor="#FFFFCC"];
+ O abox O [label="Script coin lock released"];
+ O =>> N [label="Sends script-coin-lock-spend-tx"];
+ O abox O [label="Script tx redeemed"];
+ O abox O [label="Bid Completed"];
+ --- [label="fail path"];
+ |||;
+ O => O [label="Wait for script-coin-lock-tx lock to expire"];
+ B =>> N [label="Sends script-coin-lock-pre-refund-tx"],
+ C note C2
+ [label="tx can be sent by either party.",
+ textbgcolor="#FFFFCC"];
+ N >> B [label="script-coin-lock-pre-refund-tx"];
+ O abox O [label="Bid Script pre-refund tx in chain"];
+ CB alt C [label="bidder refunds script coin lock tx"] {
+ |||;
+ B => B [label="Wait for pre-refund tx to confirm"];
+ B =>> N [label="Sends script-coin-lock-pre-refund-spend-tx"],
+ C note C2
+ [label="Refunds the script lock tx, with the bidder's cleartext signature the offerer can refund the noscript lock tx.
+ Once the lock expires the pre-refund tx can be spent by the offerer.",
+ textbgcolor="#FFFFCC"];
+ B abox B [label="Bid Failed, refunded"];
+ N >> O [label="Detects script-coin-lock-pre-refund-spend-tx"],
+ C note C2
+ [label="offerer recovers the bidder's scriptless chain key-shard.",
+ textbgcolor="#FFFFCC"];
+ O =>> N [label="Sends scriptless-coin-lock-recover-tx"];
+ O abox O [label="Bid Scriptless tx recovered"];
+ O abox O [label="Bid Failed, refunded"];
+ --- [label="offerer swipes script coin lock tx"];
+ |||;
+ O => O [label="Wait for pre-refund tx lock to expire"];
+ O =>> N [label="Sends script-coin-lock-pre-refund-swipe-tx"];
+ O abox O [label="Bid Failed, swiped"];
+ };
+ };
+}
diff --git a/doc/protocols/sequence_diagrams/notes.txt b/doc/protocols/sequence_diagrams/notes.txt
index e8e0c97..04d0c14 100644
--- a/doc/protocols/sequence_diagrams/notes.txt
+++ b/doc/protocols/sequence_diagrams/notes.txt
@@ -11,13 +11,17 @@ npm install -g mscgenjs-cli
mscgenjs -T svg -i bidder.alt.xu -o bidder.alt.xu.svg
mscgenjs -T svg -i offerer.alt.xu -o offerer.alt.xu.svg
-mscgenjs -T svg -i xmr.bidder.alt.xu -o xmr.bidder.alt.xu.svg
-mscgenjs -T svg -i xmr.offerer.alt.xu -o xmr.offerer.alt.xu.svg
+mscgenjs -T svg -i ads.bidder.alt.xu -o ads.bidder.alt.xu.svg
+mscgenjs -T svg -i ads.offerer.alt.xu -o ads.offerer.alt.xu.svg
+mscgenjs -T svg -i ads.rev.bidder.xu -o ads.rev.bidder.xu.svg
+mscgenjs -T svg -i ads.rev.offerer.xu -o ads.rev.offerer.xu.svg
npm -g install svgo
svgo --pretty bidder.alt.xu.svg -o bidder.alt.xu.min.svg
svgo --pretty offerer.alt.xu.svg -o offerer.alt.xu.min.svg
-svgo --pretty xmr.bidder.alt.xu.svg -o xmr.bidder.alt.xu.min.svg
-svgo --pretty xmr.offerer.alt.xu.svg -o xmr.offerer.alt.xu.min.svg
+svgo --pretty ads.bidder.alt.xu.svg -o ads.bidder.alt.xu.min.svg
+svgo --pretty ads.offerer.alt.xu.svg -o ads.offerer.alt.xu.min.svg
+svgo --pretty ads.rev.bidder.xu.svg -o ads.rev.bidder.xu.min.svg
+svgo --pretty ads.rev.offerer.xu.svg -o ads.rev.offerer.xu.min.svg
diff --git a/doc/release-notes.md b/doc/release-notes.md
index a542738..7584adc 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -1,4 +1,13 @@
+0.0.64
+==============
+
+- protocol: Added reversed Adaptor sig protocol.
+ - Runs the adaptor-sig protocol with leader and follower swapped to
+ enable offers from no-script coins to script coins.
+- smsg: Outbox messages are removed when expired.
+
+
0.0.63
==============
diff --git a/tests/basicswap/test_btc_xmr.py b/tests/basicswap/test_btc_xmr.py
index 687dd10..b960615 100644
--- a/tests/basicswap/test_btc_xmr.py
+++ b/tests/basicswap/test_btc_xmr.py
@@ -279,8 +279,22 @@ class BasicSwapTest(BaseTest):
logging.info('---------- Test {} to {}'.format(coin_from.name, coin_to.name))
swap_clients = self.swap_clients
+ reverse_bid: bool = coin_from in swap_clients[0].scriptless_coins
ci_from = swap_clients[0].ci(coin_from)
ci_to = swap_clients[1].ci(coin_to)
+ ci_part0 = swap_clients[0].ci(Coins.PART)
+ ci_part1 = swap_clients[1].ci(Coins.PART)
+
+ # Offerer sends the offer
+ # Bidder sends the bid
+ id_offerer: int = 0
+ id_bidder: int = 1
+
+ # Leader sends the initial (chain a) lock tx.
+ # Follower sends the participate (chain b) lock tx.
+ id_leader: int = 1 if reverse_bid else 0
+ id_follower: int = 0 if reverse_bid else 1
+ logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}')
js_0 = read_json_api(1800, 'wallets')
node0_from_before = self.getBalance(js_0, coin_from)
@@ -291,20 +305,23 @@ class BasicSwapTest(BaseTest):
js_0_to = read_json_api(1800, 'wallets/{}'.format(coin_to.name.lower()))
js_1_to = read_json_api(1801, 'wallets/{}'.format(coin_to.name.lower()))
+ node0_sent_messages_before: int = ci_part0.rpc_callback('smsgoutbox', ['count',])['num_messages']
+ node1_sent_messages_before: int = ci_part1.rpc_callback('smsgoutbox', ['count',])['num_messages']
+
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
- offer_id = swap_clients[0].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP)
- wait_for_offer(test_delay_event, swap_clients[1], offer_id)
- offers = swap_clients[0].listOffers(filters={'offer_id': offer_id})
- offer = offers[0]
+ offer_id = swap_clients[id_offerer].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP)
+ wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id)
+ offer = swap_clients[id_bidder].listOffers(filters={'offer_id': offer_id})[0]
+ assert (offer.offer_id == offer_id)
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)
- swap_clients[0].acceptBid(bid_id)
+ wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED)
+ swap_clients[id_offerer].acceptBid(bid_id)
- wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
- wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True)
+ wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
+ wait_for_bid(test_delay_event, swap_clients[id_bidder], bid_id, BidStates.SWAP_COMPLETED, sent=True)
amount_from = float(ci_from.format_amount(amt_swap))
js_1 = read_json_api(1801, 'wallets')
@@ -328,6 +345,13 @@ class BasicSwapTest(BaseTest):
if False: # TODO: set stakeaddress and xmr rewards to non wallet addresses
assert (node1_to_after < node1_to_before - amount_to_float)
+ node0_sent_messages_after: int = ci_part0.rpc_callback('smsgoutbox', ['count',])['num_messages']
+ node1_sent_messages_after: int = ci_part1.rpc_callback('smsgoutbox', ['count',])['num_messages']
+ node0_sent_messages: int = node0_sent_messages_after - node0_sent_messages_before
+ node1_sent_messages: int = node1_sent_messages_after - node1_sent_messages_before
+ assert (node0_sent_messages == (5 if reverse_bid else 6))
+ assert (node1_sent_messages == (6 if reverse_bid else 4))
+
def test_01_a_full_swap(self):
if not self.has_segwit:
return
@@ -355,13 +379,8 @@ class BasicSwapTest(BaseTest):
ci_from = swap_clients[0].ci(coin_from)
ci_to = swap_clients[0].ci(coin_to)
- # Offerer sends the offer
- # Bidder sends the bid
id_offerer: int = 0
id_bidder: int = 1
-
- # Leader sends the initial (chain a) lock tx.
- # Follower sends the participate (chain b) lock tx.
id_leader: int = 1 if reverse_bid else 0
id_follower: int = 0 if reverse_bid else 1
logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}')
diff --git a/tests/basicswap/test_xmr.py b/tests/basicswap/test_xmr.py
index 9f6ac1a..8f4515e 100644
--- a/tests/basicswap/test_xmr.py
+++ b/tests/basicswap/test_xmr.py
@@ -347,8 +347,8 @@ class BaseTest(unittest.TestCase):
logger.addHandler(stream_stdout)
diagrams_dir = 'doc/protocols/sequence_diagrams'
- cls.states_bidder = extract_states_from_xu_file(os.path.join(diagrams_dir, 'xmr.bidder.alt.xu'), 'B')
- cls.states_offerer = extract_states_from_xu_file(os.path.join(diagrams_dir, 'xmr.offerer.alt.xu'), 'O')
+ cls.states_bidder = extract_states_from_xu_file(os.path.join(diagrams_dir, 'ads.bidder.alt.xu'), 'B')
+ cls.states_offerer = extract_states_from_xu_file(os.path.join(diagrams_dir, 'ads.offerer.alt.xu'), 'O')
if os.path.isdir(TEST_DIR):
if RESET_TEST: