From 8c372cc5dc16150006dd377bdce39b1597384831 Mon Sep 17 00:00:00 2001 From: tecnovert Date: Fri, 11 Dec 2020 00:43:36 +0200 Subject: [PATCH] Simplify lock tx script. Raise version. --- basicswap/__init__.py | 2 +- basicswap/basicswap.py | 144 ++++++++++++-------------- basicswap/db.py | 8 +- basicswap/interface_btc.py | 186 +++++++--------------------------- basicswap/messages.proto | 31 +++--- basicswap/messages_pb2.py | 91 +++++++---------- tests/basicswap/test_other.py | 10 ++ 7 files changed, 159 insertions(+), 313 deletions(-) diff --git a/basicswap/__init__.py b/basicswap/__init__.py index 49710cf..517d50f 100644 --- a/basicswap/__init__.py +++ b/basicswap/__init__.py @@ -1,3 +1,3 @@ name = "basicswap" -__version__ = "0.0.6" +__version__ = "0.0.7" diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py index 5b6ef33..6b7abe1 100644 --- a/basicswap/basicswap.py +++ b/basicswap/basicswap.py @@ -60,7 +60,7 @@ from .messages_pb2 import ( XmrSplitMessage, XmrBidLockTxSigsMessage, XmrBidLockSpendTxMessage, - XmrBidSecretMessage, + XmrBidLockReleaseMessage, OfferRevokeMessage, ) from .db import ( @@ -108,7 +108,7 @@ class MessageTypes(IntEnum): XMR_BID_ACCEPT_LF = auto() XMR_BID_TXN_SIGS_FL = auto() XMR_BID_LOCK_SPEND_TX_LF = auto() - XMR_BID_SECRET_LF = auto() + XMR_BID_LOCK_RELEASE_LF = auto() OFFER_REVOKE = auto() @@ -138,7 +138,7 @@ class BidStates(IntEnum): XMR_SWAP_SCRIPT_COIN_LOCKED = auto() XMR_SWAP_HAVE_SCRIPT_COIN_SPEND_TX = auto() XMR_SWAP_NOSCRIPT_COIN_LOCKED = auto() - XMR_SWAP_SECRET_SHARED = auto() + XMR_SWAP_LOCK_RELEASED = auto() XMR_SWAP_SCRIPT_TX_REDEEMED = auto() XMR_SWAP_NOSCRIPT_TX_REDEEMED = auto() XMR_SWAP_NOSCRIPT_TX_RECOVERED = auto() @@ -181,7 +181,7 @@ class EventTypes(IntEnum): SIGN_XMR_SWAP_LOCK_TX_A = auto() SEND_XMR_SWAP_LOCK_TX_A = auto() SEND_XMR_SWAP_LOCK_TX_B = auto() - SEND_XMR_SECRET = auto() + SEND_XMR_LOCK_RELEASE = auto() REDEEM_XMR_SWAP_LOCK_TX_A = auto() # Follower REDEEM_XMR_SWAP_LOCK_TX_B = auto() # Leader RECOVER_XMR_SWAP_LOCK_TX_B = auto() @@ -257,8 +257,8 @@ def strBidState(state): return 'Script coin spend tx valid' if state == BidStates.XMR_SWAP_NOSCRIPT_COIN_LOCKED: return 'Scriptless coin locked' - if state == BidStates.XMR_SWAP_SECRET_SHARED: - return 'Secret shared' + if state == BidStates.XMR_SWAP_LOCK_RELEASED: + return 'Script coin lock released' if state == BidStates.XMR_SWAP_SCRIPT_TX_REDEEMED: return 'Script tx redeemed' if state == BidStates.XMR_SWAP_NOSCRIPT_TX_REDEEMED: @@ -1727,21 +1727,18 @@ class BasicSwap(BaseApp): kbsf = self.getPathKey(coin_from, coin_to, bid_created_at, xmr_swap.contract_count, 2, for_ed25519=True) kaf = self.getPathKey(coin_from, coin_to, bid_created_at, xmr_swap.contract_count, 3) - karf = self.getPathKey(coin_from, coin_to, bid_created_at, xmr_swap.contract_count, 4) xmr_swap.vkbvf = kbvf xmr_swap.pkbvf = ci_to.getPubkey(kbvf) xmr_swap.pkbsf = ci_to.getPubkey(kbsf) xmr_swap.pkaf = ci_from.getPubkey(kaf) - xmr_swap.pkarf = ci_from.getPubkey(karf) xmr_swap.kbsf_dleag = ci_to.proveDLEAG(kbsf) xmr_swap.pkasf = xmr_swap.kbsf_dleag[0: 33] assert(xmr_swap.pkasf == ci_from.getPubkey(kbsf)) msg_buf.pkaf = xmr_swap.pkaf - msg_buf.pkarf = xmr_swap.pkarf msg_buf.kbvf = kbvf msg_buf.kbsf_dleag = xmr_swap.kbsf_dleag[:16000] @@ -1831,13 +1828,10 @@ class BasicSwap(BaseApp): if xmr_swap.contract_count is None: xmr_swap.contract_count = self.getNewContractId() - contract_secret = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 1) + kbvl = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 1, for_ed25519=True) + kbsl = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 2, for_ed25519=True) - kbvl = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 2, for_ed25519=True) - kbsl = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 3, for_ed25519=True) - - kal = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 4) - karl = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 5) + kal = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 3) xmr_swap.vkbvl = kbvl xmr_swap.pkbvl = ci_to.getPubkey(kbvl) @@ -1847,19 +1841,14 @@ class BasicSwap(BaseApp): xmr_swap.pkbv = ci_to.sumPubkeys(xmr_swap.pkbvl, xmr_swap.pkbvf) xmr_swap.pkbs = ci_to.sumPubkeys(xmr_swap.pkbsl, xmr_swap.pkbsf) - xmr_swap.sh = hashlib.sha256(contract_secret).digest() xmr_swap.pkal = ci_from.getPubkey(kal) - xmr_swap.pkarl = ci_from.getPubkey(karl) xmr_swap.kbsl_dleag = ci_to.proveDLEAG(kbsl) # MSG2F xmr_swap.a_lock_tx, xmr_swap.a_lock_tx_script = ci_from.createScriptLockTx( bid.amount, - xmr_swap.sh, xmr_swap.pkal, xmr_swap.pkaf, - xmr_offer.lock_time_1, - xmr_swap.pkarl, xmr_swap.pkarf, ) xmr_swap.a_lock_tx = ci_from.fundTx(xmr_swap.a_lock_tx, xmr_offer.a_fee_rate) @@ -1868,15 +1857,14 @@ class BasicSwap(BaseApp): xmr_swap.a_lock_refund_tx, xmr_swap.a_lock_refund_tx_script, xmr_swap.a_swap_refund_value = ci_from.createScriptLockRefundTx( xmr_swap.a_lock_tx, xmr_swap.a_lock_tx_script, - xmr_swap.pkarl, xmr_swap.pkarf, - xmr_offer.lock_time_2, - xmr_swap.pkaf, + xmr_swap.pkal, xmr_swap.pkaf, + xmr_offer.lock_time_1, xmr_offer.lock_time_2, xmr_offer.a_fee_rate ) xmr_swap.a_lock_refund_tx_id = ci_from.getTxHash(xmr_swap.a_lock_refund_tx) - xmr_swap.al_lock_refund_tx_sig = ci_from.signTx(karl, xmr_swap.a_lock_refund_tx, 0, xmr_swap.a_lock_tx_script, bid.amount) - v = ci_from.verifyTxSig(xmr_swap.a_lock_refund_tx, xmr_swap.al_lock_refund_tx_sig, xmr_swap.pkarl, 0, xmr_swap.a_lock_tx_script, bid.amount) + xmr_swap.al_lock_refund_tx_sig = ci_from.signTx(kal, xmr_swap.a_lock_refund_tx, 0, xmr_swap.a_lock_tx_script, bid.amount) + v = ci_from.verifyTxSig(xmr_swap.a_lock_refund_tx, xmr_swap.al_lock_refund_tx_sig, xmr_swap.pkal, 0, xmr_swap.a_lock_tx_script, bid.amount) assert(v) pkh_refund_to = ci_from.decodeAddress(self.getReceiveAddressForCoin(coin_from)) @@ -1889,9 +1877,7 @@ class BasicSwap(BaseApp): msg_buf = XmrBidAcceptMessage() msg_buf.bid_msg_id = bid_id - msg_buf.sh = xmr_swap.sh msg_buf.pkal = xmr_swap.pkal - msg_buf.pkarl = xmr_swap.pkarl msg_buf.kbvl = kbvl msg_buf.kbsl_dleag = xmr_swap.kbsl_dleag[:16000] @@ -2657,13 +2643,13 @@ class BasicSwap(BaseApp): if bid.was_received: delay = random.randrange(self.min_delay_event, self.max_delay_event) - self.log.info('Releasing xmr swap secret for bid %s in %d seconds', bid_id.hex(), delay) - self.createEventInSession(delay, EventTypes.SEND_XMR_SECRET, bid_id, session) + self.log.info('Releasing xmr script coin lock tx for bid %s in %d seconds', bid_id.hex(), delay) + self.createEventInSession(delay, EventTypes.SEND_XMR_LOCK_RELEASE, bid_id, session) if bid_changed: self.saveBidInSession(bid_id, bid, session, xmr_swap) session.commit() - elif state == BidStates.XMR_SWAP_SECRET_SHARED: + elif state == BidStates.XMR_SWAP_LOCK_RELEASED: # Wait for script spend tx to confirm # TODO: Use explorer to get tx / block hash for getrawtransaction @@ -2966,7 +2952,7 @@ class BasicSwap(BaseApp): spending_txid = bytes.fromhex(spend_txid_hex) if spending_txid == xmr_swap.a_lock_spend_tx_id: - if state == BidStates.XMR_SWAP_SECRET_SHARED: + if state == BidStates.XMR_SWAP_LOCK_RELEASED: xmr_swap.a_lock_spend_tx = bytes.fromhex(spend_txn_hex) bid.setState(BidStates.XMR_SWAP_SCRIPT_TX_REDEEMED) # TODO: Wait for confirmation? @@ -3154,8 +3140,8 @@ class BasicSwap(BaseApp): self.sendXmrBidCoinALockTx(row.linked_id, session) elif row.event_type == EventTypes.SEND_XMR_SWAP_LOCK_TX_B: self.sendXmrBidCoinBLockTx(row.linked_id, session) - elif row.event_type == EventTypes.SEND_XMR_SECRET: - self.sendXmrBidSecret(row.linked_id, session) + elif row.event_type == EventTypes.SEND_XMR_LOCK_RELEASE: + self.sendXmrBidLockRelease(row.linked_id, session) elif row.event_type == EventTypes.REDEEM_XMR_SWAP_LOCK_TX_A: self.redeemXmrBidCoinALockTx(row.linked_id, session) elif row.event_type == EventTypes.REDEEM_XMR_SWAP_LOCK_TX_B: @@ -3550,8 +3536,6 @@ class BasicSwap(BaseApp): if not ci_from.verifyPubkey(xmr_swap.pkaf): raise ValueError('Invalid pubkey.') - if not ci_from.verifyPubkey(xmr_swap.pkarf): - raise ValueError('Invalid pubkey.') self.log.info('Received valid bid %s for xmr offer %s', bid.bid_id.hex(), bid.offer_id.hex()) @@ -3604,8 +3588,6 @@ class BasicSwap(BaseApp): if not ci_from.verifyPubkey(xmr_swap.pkal): raise ValueError('Invalid pubkey.') - if not ci_from.verifyPubkey(xmr_swap.pkarl): - raise ValueError('Invalid pubkey.') if xmr_swap.pkbvl == xmr_swap.pkbvf: raise ValueError('Duplicate scriptless view pubkey.') @@ -3613,8 +3595,6 @@ class BasicSwap(BaseApp): raise ValueError('Duplicate scriptless spend pubkey.') if xmr_swap.pkal == xmr_swap.pkaf: raise ValueError('Duplicate script spend pubkey.') - if xmr_swap.pkarl == xmr_swap.pkarf: - raise ValueError('Duplicate script spend pubkey.') bid.setState(BidStates.SWAP_DELAYING) self.saveBidInSession(bid.bid_id, bid, session, xmr_swap) @@ -3663,7 +3643,6 @@ class BasicSwap(BaseApp): bid_id=bid_id, dest_af=bid_data.dest_af, pkaf=bid_data.pkaf, - pkarf=bid_data.pkarf, vkbvf=bid_data.kbvf, pkbvf=ci_to.getPubkey(bid_data.kbvf), kbsf_dleag=bid_data.kbsf_dleag, @@ -3702,11 +3681,7 @@ class BasicSwap(BaseApp): ci_to = self.ci(Coins(offer.coin_to)) try: - assert(len(msg_data.sh) == 32), 'Bad secret hash length' - - xmr_swap.sh = msg_data.sh xmr_swap.pkal = msg_data.pkal - xmr_swap.pkarl = msg_data.pkarl xmr_swap.vkbvl = msg_data.kbvl xmr_swap.pkbvl = ci_to.getPubkey(msg_data.kbvl) xmr_swap.kbsl_dleag = msg_data.kbsl_dleag @@ -3724,10 +3699,8 @@ class BasicSwap(BaseApp): xmr_swap.a_lock_tx_id, xmr_swap.a_lock_tx_vout = ci_from.verifyLockTx( xmr_swap.a_lock_tx, xmr_swap.a_lock_tx_script, bid.amount, - xmr_swap.sh, xmr_swap.pkal, xmr_swap.pkaf, - xmr_offer.lock_time_1, xmr_offer.a_fee_rate, - xmr_swap.pkarl, xmr_swap.pkarf, + xmr_offer.a_fee_rate, check_a_lock_tx_inputs ) a_lock_tx_dest = ci_from.getScriptDest(xmr_swap.a_lock_tx_script) @@ -3735,9 +3708,8 @@ class BasicSwap(BaseApp): xmr_swap.a_lock_refund_tx_id, xmr_swap.a_swap_refund_value = ci_from.verifyLockRefundTx( xmr_swap.a_lock_refund_tx, xmr_swap.a_lock_refund_tx_script, xmr_swap.a_lock_tx_id, xmr_swap.a_lock_tx_vout, xmr_offer.lock_time_1, xmr_swap.a_lock_tx_script, - xmr_swap.pkarl, xmr_swap.pkarf, + xmr_swap.pkal, xmr_swap.pkaf, xmr_offer.lock_time_2, - xmr_swap.pkaf, bid.amount, xmr_offer.a_fee_rate ) @@ -3749,7 +3721,7 @@ class BasicSwap(BaseApp): ) logging.info('Checking leader\'s lock refund tx signature') - v = ci_from.verifyTxSig(xmr_swap.a_lock_refund_tx, xmr_swap.al_lock_refund_tx_sig, xmr_swap.pkarl, 0, xmr_swap.a_lock_tx_script, bid.amount) + v = ci_from.verifyTxSig(xmr_swap.a_lock_refund_tx, xmr_swap.al_lock_refund_tx_sig, xmr_swap.pkal, 0, xmr_swap.a_lock_tx_script, bid.amount) bid.setState(BidStates.BID_RECEIVING_ACC) self.saveBid(bid.bid_id, bid, xmr_swap=xmr_swap) @@ -3785,10 +3757,10 @@ class BasicSwap(BaseApp): ci_to = self.ci(coin_to) try: - karf = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 4) + kaf = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 3) - xmr_swap.af_lock_refund_spend_tx_esig = ci_from.signTxOtVES(karf, xmr_swap.pkasl, xmr_swap.a_lock_refund_spend_tx, 0, xmr_swap.a_lock_refund_tx_script, xmr_swap.a_swap_refund_value) - xmr_swap.af_lock_refund_tx_sig = ci_from.signTx(karf, xmr_swap.a_lock_refund_tx, 0, xmr_swap.a_lock_tx_script, bid.amount) + xmr_swap.af_lock_refund_spend_tx_esig = ci_from.signTxOtVES(kaf, xmr_swap.pkasl, xmr_swap.a_lock_refund_spend_tx, 0, xmr_swap.a_lock_refund_tx_script, xmr_swap.a_swap_refund_value) + xmr_swap.af_lock_refund_tx_sig = ci_from.signTx(kaf, xmr_swap.a_lock_refund_tx, 0, xmr_swap.a_lock_tx_script, bid.amount) self.addLockRefundSigs(xmr_swap, ci_from) @@ -3843,7 +3815,7 @@ class BasicSwap(BaseApp): ci_from = self.ci(coin_from) ci_to = self.ci(coin_to) - kal = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 4) + kal = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 3) xmr_swap.a_lock_spend_tx = ci_from.createScriptLockSpendTx( xmr_swap.a_lock_tx, xmr_swap.a_lock_tx_script, @@ -3853,10 +3825,13 @@ class BasicSwap(BaseApp): xmr_swap.a_lock_spend_tx_id = ci_from.getTxHash(xmr_swap.a_lock_spend_tx) xmr_swap.al_lock_spend_tx_esig = ci_from.signTxOtVES(kal, xmr_swap.pkasf, xmr_swap.a_lock_spend_tx, 0, xmr_swap.a_lock_tx_script, bid.amount) # self.a_swap_value + # Proof leader can sign for kal + xmr_swap.kal_sig = ci_from.signCompact(kal, 'proof key owned for swap') + msg_buf = XmrBidLockSpendTxMessage( bid_msg_id=bid_id, a_lock_spend_tx=xmr_swap.a_lock_spend_tx, - al_lock_spend_tx_esig=xmr_swap.al_lock_spend_tx_esig) + kal_sig=xmr_swap.kal_sig) msg_bytes = msg_buf.SerializeToString() payload_hex = str.format('{:02x}', MessageTypes.XMR_BID_LOCK_SPEND_TX_LF) + msg_bytes.hex() @@ -3947,7 +3922,7 @@ class BasicSwap(BaseApp): self.saveBidInSession(bid_id, bid, session, xmr_swap, save_in_progress=offer) - def sendXmrBidSecret(self, bid_id, session): + def sendXmrBidLockRelease(self, bid_id, session): # Leader sending lock tx a release secret (MSG5F) self.log.debug('Sending bid secret for xmr bid %s', bid_id.hex()) @@ -3961,14 +3936,12 @@ class BasicSwap(BaseApp): coin_from = Coins(offer.coin_from) coin_to = Coins(offer.coin_to) - contract_secret = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 1) - - msg_buf = XmrBidSecretMessage( + msg_buf = XmrBidLockReleaseMessage( bid_msg_id=bid_id, - secret_value=contract_secret) + al_lock_spend_tx_esig=xmr_swap.al_lock_spend_tx_esig) msg_bytes = msg_buf.SerializeToString() - payload_hex = str.format('{:02x}', MessageTypes.XMR_BID_SECRET_LF) + msg_bytes.hex() + payload_hex = str.format('{:02x}', MessageTypes.XMR_BID_LOCK_RELEASE_LF) + msg_bytes.hex() options = {'decodehex': True, 'ttl_is_seconds': True} # TODO: set msg_valid based on bid / offer parameters @@ -3976,7 +3949,7 @@ class BasicSwap(BaseApp): ro = self.callrpc('smsgsend', [offer.addr_from, bid.bid_addr, payload_hex, False, msg_valid, False, options]) xmr_swap.coin_a_lock_refund_spend_tx_msg_id = bytes.fromhex(ro['msgid']) - bid.setState(BidStates.XMR_SWAP_SECRET_SHARED) + bid.setState(BidStates.XMR_SWAP_LOCK_RELEASED) self.saveBidInSession(bid_id, bid, session, xmr_swap, save_in_progress=offer) def redeemXmrBidCoinALockTx(self, bid_id, session): @@ -4010,8 +3983,6 @@ class BasicSwap(BaseApp): b'', al_lock_spend_sig, af_lock_spend_sig, - xmr_swap.sv, - bytes((1,)), xmr_swap.a_lock_tx_script, ] @@ -4050,7 +4021,7 @@ class BasicSwap(BaseApp): kbsf = ci_from.recoverEncKey(xmr_swap.al_lock_spend_tx_esig, xmr_swap.al_lock_spend_tx_sig, xmr_swap.pkasf) assert(kbsf is not None) - kbsl = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 3, for_ed25519=True) + kbsl = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 2, for_ed25519=True) vkbs = ci_to.sumKeys(kbsl, kbsf) address_to = ci_to.getMainWalletAddress() @@ -4144,11 +4115,11 @@ class BasicSwap(BaseApp): xmr_swap.af_lock_refund_spend_tx_esig = msg_data.af_lock_refund_spend_tx_esig xmr_swap.af_lock_refund_tx_sig = msg_data.af_lock_refund_tx_sig - kbsl = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 3, for_ed25519=True) - karl = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 5) + kbsl = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 2, for_ed25519=True) + kal = self.getPathKey(coin_from, coin_to, bid.created_at, xmr_swap.contract_count, 3) xmr_swap.af_lock_refund_spend_tx_sig = ci_from.decryptOtVES(kbsl, xmr_swap.af_lock_refund_spend_tx_esig) - al_lock_refund_spend_tx_sig = ci_from.signTx(karl, xmr_swap.a_lock_refund_spend_tx, 0, xmr_swap.a_lock_refund_tx_script, xmr_swap.a_swap_refund_value) + al_lock_refund_spend_tx_sig = ci_from.signTx(kal, xmr_swap.a_lock_refund_spend_tx, 0, xmr_swap.a_lock_refund_tx_script, xmr_swap.a_swap_refund_value) self.log.debug('Setting lock refund spend tx sigs') witness_stack = [ @@ -4162,7 +4133,7 @@ class BasicSwap(BaseApp): assert(signed_tx), 'setTxSignature failed' xmr_swap.a_lock_refund_spend_tx = signed_tx - v = ci_from.verifyTxSig(xmr_swap.a_lock_refund_spend_tx, xmr_swap.af_lock_refund_spend_tx_sig, xmr_swap.pkarf, 0, xmr_swap.a_lock_refund_tx_script, xmr_swap.a_swap_refund_value) + v = ci_from.verifyTxSig(xmr_swap.a_lock_refund_spend_tx, xmr_swap.af_lock_refund_spend_tx_sig, xmr_swap.pkaf, 0, xmr_swap.a_lock_refund_tx_script, xmr_swap.a_swap_refund_value) assert(v), 'Invalid signature for lock refund spend txn' self.addLockRefundSigs(xmr_swap, ci_from) @@ -4201,17 +4172,14 @@ class BasicSwap(BaseApp): try: xmr_swap.a_lock_spend_tx = msg_data.a_lock_spend_tx xmr_swap.a_lock_spend_tx_id = ci_from.getTxHash(xmr_swap.a_lock_spend_tx) - xmr_swap.al_lock_spend_tx_esig = msg_data.al_lock_spend_tx_esig + xmr_swap.kal_sig = msg_data.kal_sig ci_from.verifyLockSpendTx( xmr_swap.a_lock_spend_tx, xmr_swap.a_lock_tx, xmr_swap.a_lock_tx_script, xmr_swap.dest_af, xmr_offer.a_fee_rate) - v = ci_from.verifyTxOtVES( - xmr_swap.a_lock_spend_tx, xmr_swap.al_lock_spend_tx_esig, - xmr_swap.pkal, xmr_swap.pkasf, 0, xmr_swap.a_lock_tx_script, bid.amount) - assert(v), 'verifyTxOtVES failed' + ci_from.verifyCompact(xmr_swap.pkal, 'proof key owned for swap', xmr_swap.kal_sig) bid.setState(BidStates.XMR_SWAP_HAVE_SCRIPT_COIN_SPEND_TX) self.saveBid(bid_id, bid, xmr_swap=xmr_swap) @@ -4242,11 +4210,11 @@ class BasicSwap(BaseApp): dbr.created_at = now self.saveToDB(dbr) - def processXmrSecretMessage(self, msg): + def processXmrLockReleaseMessage(self, msg): self.log.debug('Processing xmr secret msg %s', msg['msgid']) now = int(time.time()) msg_bytes = bytes.fromhex(msg['hex'][2:-2]) - msg_data = XmrBidSecretMessage() + msg_data = XmrBidLockReleaseMessage() msg_data.ParseFromString(msg_bytes) # Validate data @@ -4260,14 +4228,27 @@ class BasicSwap(BaseApp): offer, xmr_offer = self.getXmrOffer(bid.offer_id, sent=False) assert(offer), 'Offer not found: {}.'.format(bid.offer_id.hex()) assert(xmr_offer), 'XMR offer not found: {}.'.format(bid.offer_id.hex()) + ci_from = self.ci(Coins(offer.coin_from)) - xmr_swap.sv = msg_data.secret_value + xmr_swap.al_lock_spend_tx_esig = msg_data.al_lock_spend_tx_esig + + try: + v = ci_from.verifyTxOtVES( + xmr_swap.a_lock_spend_tx, xmr_swap.al_lock_spend_tx_esig, + xmr_swap.pkal, xmr_swap.pkasf, 0, xmr_swap.a_lock_tx_script, bid.amount) + assert(v), 'verifyTxOtVES failed' + except Exception as e: + if self.debug: + traceback.print_exc() + self.setBidError(bid_id, bid, str(ex)) + self.swaps_in_progress[bid_id] = (bid, offer) + return delay = random.randrange(self.min_delay_event, self.max_delay_event) self.log.info('Redeeming coin A lock tx for xmr bid %s in %d seconds', bid_id.hex(), delay) self.createEvent(delay, EventTypes.REDEEM_XMR_SWAP_LOCK_TX_A, bid_id) - bid.setState(BidStates.XMR_SWAP_SECRET_SHARED) + bid.setState(BidStates.XMR_SWAP_LOCK_RELEASED) self.saveBid(bid_id, bid, xmr_swap=xmr_swap) self.swaps_in_progress[bid_id] = (bid, offer) @@ -4293,8 +4274,8 @@ class BasicSwap(BaseApp): self.processXmrBidLockSpendTx(msg) elif msg_type == MessageTypes.XMR_BID_SPLIT: self.processXmrSplitMessage(msg) - elif msg_type == MessageTypes.XMR_BID_SECRET_LF: - self.processXmrSecretMessage(msg) + elif msg_type == MessageTypes.XMR_BID_LOCK_RELEASE_LF: + self.processXmrLockReleaseMessage(msg) if msg_type == MessageTypes.OFFER_REVOKE: self.processOfferRevoke(msg) @@ -4409,7 +4390,7 @@ class BasicSwap(BaseApp): else: self.log.debug('TODO - determine in-progress for manualBidUpdate') if offer.swap_type == SwapTypes.XMR_SWAP: - if bid.state and bid.state in (BidStates.XMR_SWAP_SECRET_SHARED, BidStates.XMR_SWAP_NOSCRIPT_TX_REDEEMED): + if bid.state and bid.state in (BidStates.XMR_SWAP_LOCK_RELEASED, BidStates.XMR_SWAP_NOSCRIPT_TX_REDEEMED): activate_bid = True if activate_bid: @@ -4635,7 +4616,6 @@ class BasicSwap(BaseApp): b'', xmr_swap.al_lock_refund_tx_sig, xmr_swap.af_lock_refund_tx_sig, - b'', xmr_swap.a_lock_tx_script, ] diff --git a/basicswap/db.py b/basicswap/db.py index 866bfee..f9b00b8 100644 --- a/basicswap/db.py +++ b/basicswap/db.py @@ -12,7 +12,7 @@ from sqlalchemy.ext.declarative import declarative_base from enum import IntEnum, auto -CURRENT_DB_VERSION = 5 +CURRENT_DB_VERSION = 6 Base = declarative_base() @@ -264,17 +264,12 @@ class XmrSwap(Base): contract_count = sa.Column(sa.Integer) - sv = sa.Column(sa.LargeBinary) # Secret value - sh = sa.Column(sa.LargeBinary) # Secret hash - dest_af = sa.Column(sa.LargeBinary) # Destination for coin A amount to follower when swap completes successfully pkal = sa.Column(sa.LargeBinary) - pkarl = sa.Column(sa.LargeBinary) pkasl = sa.Column(sa.LargeBinary) pkaf = sa.Column(sa.LargeBinary) - pkarf = sa.Column(sa.LargeBinary) pkasf = sa.Column(sa.LargeBinary) vkbvl = sa.Column(sa.LargeBinary) @@ -315,6 +310,7 @@ class XmrSwap(Base): a_lock_spend_tx = sa.Column(sa.LargeBinary) a_lock_spend_tx_id = sa.Column(sa.LargeBinary) al_lock_spend_tx_esig = sa.Column(sa.LargeBinary) + kal_sig = sa.Column(sa.LargeBinary) a_lock_refund_swipe_tx = sa.Column(sa.LargeBinary) # Follower spends script coin lock refund tx diff --git a/basicswap/interface_btc.py b/basicswap/interface_btc.py index 6bd2651..4305965 100644 --- a/basicswap/interface_btc.py +++ b/basicswap/interface_btc.py @@ -20,6 +20,7 @@ from .util import ( toWIF, decodeAddress) from coincurve.keys import ( + PrivateKey, PublicKey) from coincurve.dleag import ( verify_secp256k1_point) @@ -221,72 +222,30 @@ class BTCInterface(CoinInterface): def extractScriptLockScriptValues(self, script_bytes): script_len = len(script_bytes) - assert_cond(script_len > 112, 'Bad script length') - assert_cond(script_bytes[0] == OP_IF) - assert_cond(script_bytes[1] == OP_SIZE) - assert_cond(script_bytes[2:4] == bytes((1, 32))) # 0120, CScriptNum length, then data - assert_cond(script_bytes[4] == OP_EQUALVERIFY) - assert_cond(script_bytes[5] == OP_SHA256) - assert_cond(script_bytes[6] == 32) - secret_hash = script_bytes[7: 7 + 32] - assert_cond(script_bytes[39] == OP_EQUALVERIFY) - assert_cond(script_bytes[40] == OP_2) - assert_cond(script_bytes[41] == 33) - pk1 = script_bytes[42: 42 + 33] - assert_cond(script_bytes[75] == 33) - pk2 = script_bytes[76: 76 + 33] - assert_cond(script_bytes[109] == OP_2) - assert_cond(script_bytes[110] == OP_CHECKMULTISIG) - assert_cond(script_bytes[111] == OP_ELSE) - o = 112 - - # Decode script num - csv_val, nb = decodeScriptNum(script_bytes, o) - o += nb - - assert_cond(script_len == o + 8 + 66, 'Bad script length') # Fails if script too long - assert_cond(script_bytes[o] == OP_CHECKSEQUENCEVERIFY) - o += 1 - assert_cond(script_bytes[o] == OP_DROP) - o += 1 + assert_cond(script_len == 71, 'Bad script length') + o = 0 assert_cond(script_bytes[o] == OP_2) - o += 1 - assert_cond(script_bytes[o] == 33) - o += 1 - pk3 = script_bytes[o: o + 33] + assert_cond(script_bytes[o + 1] == 33) + o += 2 + pk1 = script_bytes[o: o + 33] o += 33 assert_cond(script_bytes[o] == 33) o += 1 - pk4 = script_bytes[o: o + 33] + pk2 = script_bytes[o: o + 33] o += 33 assert_cond(script_bytes[o] == OP_2) - o += 1 - assert_cond(script_bytes[o] == OP_CHECKMULTISIG) - o += 1 - assert_cond(script_bytes[o] == OP_ENDIF) + assert_cond(script_bytes[o + 1] == OP_CHECKMULTISIG) - return secret_hash, pk1, pk2, csv_val, pk3, pk4 - - def genScriptLockTxScript(self, sh, Kal, Kaf, lock_blocks, Karl, Karf): + return pk1, pk2 + def genScriptLockTxScript(self, Kal, Kaf): Kal_enc = Kal if len(Kal) == 33 else self.encodePubkey(Kal) Kaf_enc = Kaf if len(Kaf) == 33 else self.encodePubkey(Kaf) - Karl_enc = Karl if len(Karl) == 33 else self.encodePubkey(Karl) - Karf_enc = Karf if len(Karf) == 33 else self.encodePubkey(Karf) - return CScript([ - CScriptOp(OP_IF), - CScriptOp(OP_SIZE), 32, CScriptOp(OP_EQUALVERIFY), - CScriptOp(OP_SHA256), sh, CScriptOp(OP_EQUALVERIFY), - 2, Kal_enc, Kaf_enc, 2, CScriptOp(OP_CHECKMULTISIG), - CScriptOp(OP_ELSE), - lock_blocks, CScriptOp(OP_CHECKSEQUENCEVERIFY), CScriptOp(OP_DROP), - 2, Karl_enc, Karf_enc, 2, CScriptOp(OP_CHECKMULTISIG), - CScriptOp(OP_ENDIF)]) + return CScript([2, Kal_enc, Kaf_enc, 2, CScriptOp(OP_CHECKMULTISIG)]) - def createScriptLockTx(self, value, sh, Kal, Kaf, lock_blocks, Karl, Karf): - - script = self.genScriptLockTxScript(sh, Kal, Kaf, lock_blocks, Karl, Karf) + def createScriptLockTx(self, value, Kal, Kaf): + script = self.genScriptLockTxScript(Kal, Kaf) tx = CTransaction() tx.nVersion = self.txVersion() tx.vout.append(self.txoType(value, self.getScriptDest(script))) @@ -324,21 +283,20 @@ class BTCInterface(CoinInterface): return pk1, pk2, csv_val, pk3 - def genScriptLockRefundTxScript(self, Karl, Karf, csv_val, Kaf): + def genScriptLockRefundTxScript(self, Kal, Kaf, csv_val): + Kal_enc = Kal if len(Kal) == 33 else self.encodePubkey(Kal) Kaf_enc = Kaf if len(Kaf) == 33 else self.encodePubkey(Kaf) - Karl_enc = Karl if len(Karl) == 33 else self.encodePubkey(Karl) - Karf_enc = Karf if len(Karf) == 33 else self.encodePubkey(Karf) return CScript([ CScriptOp(OP_IF), - 2, Karl_enc, Karf_enc, 2, CScriptOp(OP_CHECKMULTISIG), + 2, Kal_enc, Kaf_enc, 2, CScriptOp(OP_CHECKMULTISIG), CScriptOp(OP_ELSE), csv_val, CScriptOp(OP_CHECKSEQUENCEVERIFY), CScriptOp(OP_DROP), Kaf_enc, CScriptOp(OP_CHECKSIG), CScriptOp(OP_ENDIF)]) - def createScriptLockRefundTx(self, tx_lock_bytes, script_lock, Karl, Karf, csv_val, Kaf, tx_fee_rate): + def createScriptLockRefundTx(self, tx_lock_bytes, script_lock, Kal, Kaf, lock1_value, csv_val, tx_fee_rate): tx_lock = CTransaction() tx_lock = FromHex(tx_lock, tx_lock_bytes.hex()) @@ -350,9 +308,7 @@ class BTCInterface(CoinInterface): tx_lock.rehash() tx_lock_hash_int = tx_lock.sha256 - sh, A, B, lock1_value, C, D = self.extractScriptLockScriptValues(script_lock) - - refund_script = self.genScriptLockRefundTxScript(Karl, Karf, csv_val, Kaf) + refund_script = self.genScriptLockRefundTxScript(Kal, Kaf, csv_val) tx = CTransaction() tx.nVersion = self.txVersion() tx.vin.append(CTxIn(COutPoint(tx_lock_hash_int, locked_n), nSequence=lock1_value)) @@ -475,10 +431,8 @@ class BTCInterface(CoinInterface): def verifyLockTx(self, tx_bytes, script_out, swap_value, - sh, Kal, Kaf, - lock_value, feerate, - Karl, Karf, + feerate, check_lock_tx_inputs): # Verify: # @@ -502,13 +456,9 @@ class BTCInterface(CoinInterface): assert_cond(locked_coin == swap_value, 'Bad locked value') # Check script and values - shv, A, B, csv_val, C, D = self.extractScriptLockScriptValues(script_out) - assert_cond(shv == sh, 'Bad hash lock') + A, B = self.extractScriptLockScriptValues(script_out) assert_cond(A == Kal, 'Bad script pubkey') assert_cond(B == Kaf, 'Bad script pubkey') - assert_cond(csv_val == lock_value, 'Bad script csv value') - assert_cond(C == Karl, 'Bad script pubkey') - assert_cond(D == Karf, 'Bad script pubkey') if check_lock_tx_inputs: # Check that inputs are unspent and verify fee rate @@ -547,7 +497,7 @@ class BTCInterface(CoinInterface): def verifyLockRefundTx(self, tx_bytes, script_out, prevout_id, prevout_n, prevout_seq, prevout_script, - Karl, Karf, csv_val_expect, Kaf, swap_value, feerate): + Kal, Kaf, csv_val_expect, swap_value, feerate): # Verify: # Must have only one input with correct prevout and sequence # Must have only one output to the p2wsh of the lock refund script @@ -574,8 +524,8 @@ class BTCInterface(CoinInterface): # Check script and values A, B, csv_val, C = self.extractScriptLockRefundScriptValues(script_out) - assert_cond(A == Karl, 'Bad script pubkey') - assert_cond(B == Karf, 'Bad script pubkey') + assert_cond(A == Kal, 'Bad script pubkey') + assert_cond(B == Kaf, 'Bad script pubkey') assert_cond(csv_val == csv_val_expect, 'Bad script csv value') assert_cond(C == Kaf, 'Bad script pubkey') @@ -892,87 +842,21 @@ class BTCInterface(CoinInterface): params = [addr_to, value, '', '', subfee, True, self._conf_target] return self.rpc_callback('sendtoaddress', params) + def signCompact(self, k, message): + message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest() + + privkey = PrivateKey(k) + return privkey.sign_recoverable(message_hash, hasher=None)[:64] + + def verifyCompact(self, K, message, sig): + message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest() + pubkey = PublicKey(K) + rv = pubkey.verify_compact(sig, message_hash, hasher=None) + assert(rv is True) + def testBTCInterface(): print('testBTCInterface') - script_bytes = bytes.fromhex('6382012088a820aaf125ff9a34a74c7a17f5e7ee9d07d17cc5e53a539f345d5f73baa7e79b65e28852210224019219ad43c47288c937ae508f26998dd81ec066827773db128fd5e262c04f21039a0fd752bd1a2234820707852e7a30253620052ecd162948a06532a817710b5952ae670114b2755221038689deba25c5578e5457ddadbaf8aeb8badf438dc22f540503dbd4ae10e14f512103c9c5d5acc996216d10852a72cd67c701bfd4b9137a4076350fd32f08db39575552ae68') - i = BTCInterface(None) - sh, a, b, csv_val, c, d = i.extractScriptLockScriptValues(script_bytes) - assert(csv_val == 20) - - script_bytes_t = script_bytes + bytes((0x00,)) - try: - sh, a, b, csv_val, c, d = i.extractScriptLockScriptValues(script_bytes_t) - assert(False), 'Should fail' - except Exception as e: - assert(str(e) == 'Bad script length') - - script_bytes_t = script_bytes[:-1] - try: - sh, a, b, csv_val, c, d = i.extractScriptLockScriptValues(script_bytes_t) - assert(False), 'Should fail' - except Exception as e: - assert(str(e) == 'Bad script length') - - script_bytes_t = bytes((0x00,)) + script_bytes[1:] - try: - sh, a, b, csv_val, c, d = i.extractScriptLockScriptValues(script_bytes_t) - assert(False), 'Should fail' - except Exception as e: - assert(str(e) == 'Bad opcode') - - # Remove the csv value - script_part_a = script_bytes[:112] - script_part_b = script_bytes[114:] - - script_bytes_t = script_part_a + bytes((0x00,)) + script_part_b - sh, a, b, csv_val, c, d = i.extractScriptLockScriptValues(script_bytes_t) - assert(csv_val == 0) - - script_bytes_t = script_part_a + bytes((OP_16,)) + script_part_b - sh, a, b, csv_val, c, d = i.extractScriptLockScriptValues(script_bytes_t) - assert(csv_val == 16) - - script_bytes_t = script_part_a + CScriptNum.encode(CScriptNum(17)) + script_part_b - sh, a, b, csv_val, c, d = i.extractScriptLockScriptValues(script_bytes_t) - assert(csv_val == 17) - - script_bytes_t = script_part_a + CScriptNum.encode(CScriptNum(-15)) + script_part_b - sh, a, b, csv_val, c, d = i.extractScriptLockScriptValues(script_bytes_t) - assert(csv_val == -15) - - script_bytes_t = script_part_a + CScriptNum.encode(CScriptNum(4000)) + script_part_b - sh, a, b, csv_val, c, d = i.extractScriptLockScriptValues(script_bytes_t) - assert(csv_val == 4000) - - max_pos = 0x7FFFFFFF - script_bytes_t = script_part_a + CScriptNum.encode(CScriptNum(max_pos)) + script_part_b - sh, a, b, csv_val, c, d = i.extractScriptLockScriptValues(script_bytes_t) - assert(csv_val == max_pos) - script_bytes_t = script_part_a + CScriptNum.encode(CScriptNum(max_pos - 1)) + script_part_b - sh, a, b, csv_val, c, d = i.extractScriptLockScriptValues(script_bytes_t) - assert(csv_val == max_pos - 1) - - script_bytes_t = script_part_a + CScriptNum.encode(CScriptNum(max_pos + 1)) + script_part_b - try: - sh, a, b, csv_val, c, d = i.extractScriptLockScriptValues(script_bytes_t) - assert(False), 'Should fail' - except Exception as e: - assert(str(e) == 'Bad scriptnum length') - - min_neg = -2147483647 - script_bytes_t = script_part_a + CScriptNum.encode(CScriptNum(min_neg)) + script_part_b - sh, a, b, csv_val, c, d = i.extractScriptLockScriptValues(script_bytes_t) - assert(csv_val == min_neg) - - script_bytes_t = script_part_a + CScriptNum.encode(CScriptNum(min_neg - 1)) + script_part_b - try: - sh, a, b, csv_val, c, d = i.extractScriptLockScriptValues(script_bytes_t) - assert(False), 'Should fail' - except Exception as e: - assert(str(e) == 'Bad scriptnum length') - - print('Passed.') if __name__ == "__main__": diff --git a/basicswap/messages.proto b/basicswap/messages.proto index 162fbb1..c400c06 100644 --- a/basicswap/messages.proto +++ b/basicswap/messages.proto @@ -63,12 +63,11 @@ message XmrBidMessage { uint64 amount = 3; /* amount of amount_from bid is for */ bytes pkaf = 4; - bytes pkarf = 5; - bytes kbvf = 6; - bytes kbsf_dleag = 7; + bytes kbvf = 5; + bytes kbsf_dleag = 6; - bytes dest_af = 8; + bytes dest_af = 7; } message XmrSplitMessage { @@ -81,20 +80,18 @@ message XmrSplitMessage { message XmrBidAcceptMessage { bytes bid_msg_id = 1; - bytes sh = 2; bytes pkal = 3; - bytes pkarl = 4; - bytes kbvl = 5; - bytes kbsl_dleag = 6; + bytes kbvl = 4; + bytes kbsl_dleag = 5; /* MSG2F */ - bytes a_lock_tx = 7; - bytes a_lock_tx_script = 8; - bytes a_lock_refund_tx = 9; - bytes a_lock_refund_tx_script = 10; - bytes a_lock_refund_spend_tx = 11; - bytes al_lock_refund_tx_sig = 12; + bytes a_lock_tx = 6; + bytes a_lock_tx_script = 7; + bytes a_lock_refund_tx = 8; + bytes a_lock_refund_tx_script = 9; + bytes a_lock_refund_spend_tx = 10; + bytes al_lock_refund_tx_sig = 11; } message XmrBidLockTxSigsMessage { @@ -110,12 +107,12 @@ message XmrBidLockSpendTxMessage { bytes bid_msg_id = 1; bytes a_lock_spend_tx = 2; - bytes al_lock_spend_tx_esig = 3; + bytes kal_sig = 3; } -message XmrBidSecretMessage { +message XmrBidLockReleaseMessage { /* MSG5F */ bytes bid_msg_id = 1; - bytes secret_value = 2; + bytes al_lock_spend_tx_esig = 2; } diff --git a/basicswap/messages_pb2.py b/basicswap/messages_pb2.py index 2d0d116..e306fe5 100644 --- a/basicswap/messages_pb2.py +++ b/basicswap/messages_pb2.py @@ -19,7 +19,7 @@ DESCRIPTOR = _descriptor.FileDescriptor( syntax='proto3', serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x0emessages.proto\x12\tbasicswap\"\xd8\x03\n\x0cOfferMessage\x12\x11\n\tcoin_from\x18\x01 \x01(\r\x12\x0f\n\x07\x63oin_to\x18\x02 \x01(\r\x12\x13\n\x0b\x61mount_from\x18\x03 \x01(\x04\x12\x0c\n\x04rate\x18\x04 \x01(\x04\x12\x16\n\x0emin_bid_amount\x18\x05 \x01(\x04\x12\x12\n\ntime_valid\x18\x06 \x01(\x04\x12\x33\n\tlock_type\x18\x07 \x01(\x0e\x32 .basicswap.OfferMessage.LockType\x12\x12\n\nlock_value\x18\x08 \x01(\r\x12\x11\n\tswap_type\x18\t \x01(\r\x12\x15\n\rproof_address\x18\n \x01(\t\x12\x17\n\x0fproof_signature\x18\x0b \x01(\t\x12\x15\n\rpkhash_seller\x18\x0c \x01(\x0c\x12\x13\n\x0bsecret_hash\x18\r \x01(\x0c\x12\x15\n\rfee_rate_from\x18\x0e \x01(\x04\x12\x13\n\x0b\x66\x65\x65_rate_to\x18\x0f \x01(\x04\"q\n\x08LockType\x12\x0b\n\x07NOT_SET\x10\x00\x12\x18\n\x14SEQUENCE_LOCK_BLOCKS\x10\x01\x12\x16\n\x12SEQUENCE_LOCK_TIME\x10\x02\x12\x13\n\x0f\x41\x42S_LOCK_BLOCKS\x10\x03\x12\x11\n\rABS_LOCK_TIME\x10\x04\"\x8c\x01\n\nBidMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x12\n\ntime_valid\x18\x02 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\x12\x14\n\x0cpkhash_buyer\x18\x04 \x01(\x0c\x12\x15\n\rproof_address\x18\x05 \x01(\t\x12\x17\n\x0fproof_signature\x18\x06 \x01(\t\"V\n\x10\x42idAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x15\n\rinitiate_txid\x18\x02 \x01(\x0c\x12\x17\n\x0f\x63ontract_script\x18\x03 \x01(\x0c\"=\n\x12OfferRevokeMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x11\n\tsignature\x18\x02 \x01(\x0c\"\x99\x01\n\rXmrBidMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x12\n\ntime_valid\x18\x02 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\x12\x0c\n\x04pkaf\x18\x04 \x01(\x0c\x12\r\n\x05pkarf\x18\x05 \x01(\x0c\x12\x0c\n\x04kbvf\x18\x06 \x01(\x0c\x12\x12\n\nkbsf_dleag\x18\x07 \x01(\x0c\x12\x0f\n\x07\x64\x65st_af\x18\x08 \x01(\x0c\"T\n\x0fXmrSplitMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x10\n\x08msg_type\x18\x02 \x01(\r\x12\x10\n\x08sequence\x18\x03 \x01(\r\x12\r\n\x05\x64leag\x18\x04 \x01(\x0c\"\x9b\x02\n\x13XmrBidAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\n\n\x02sh\x18\x02 \x01(\x0c\x12\x0c\n\x04pkal\x18\x03 \x01(\x0c\x12\r\n\x05pkarl\x18\x04 \x01(\x0c\x12\x0c\n\x04kbvl\x18\x05 \x01(\x0c\x12\x12\n\nkbsl_dleag\x18\x06 \x01(\x0c\x12\x11\n\ta_lock_tx\x18\x07 \x01(\x0c\x12\x18\n\x10\x61_lock_tx_script\x18\x08 \x01(\x0c\x12\x18\n\x10\x61_lock_refund_tx\x18\t \x01(\x0c\x12\x1f\n\x17\x61_lock_refund_tx_script\x18\n \x01(\x0c\x12\x1e\n\x16\x61_lock_refund_spend_tx\x18\x0b \x01(\x0c\x12\x1d\n\x15\x61l_lock_refund_tx_sig\x18\x0c \x01(\x0c\"r\n\x17XmrBidLockTxSigsMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12$\n\x1c\x61\x66_lock_refund_spend_tx_esig\x18\x02 \x01(\x0c\x12\x1d\n\x15\x61\x66_lock_refund_tx_sig\x18\x03 \x01(\x0c\"f\n\x18XmrBidLockSpendTxMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x17\n\x0f\x61_lock_spend_tx\x18\x02 \x01(\x0c\x12\x1d\n\x15\x61l_lock_spend_tx_esig\x18\x03 \x01(\x0c\"?\n\x13XmrBidSecretMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x14\n\x0csecret_value\x18\x02 \x01(\x0c\x62\x06proto3' + serialized_pb=b'\n\x0emessages.proto\x12\tbasicswap\"\xd8\x03\n\x0cOfferMessage\x12\x11\n\tcoin_from\x18\x01 \x01(\r\x12\x0f\n\x07\x63oin_to\x18\x02 \x01(\r\x12\x13\n\x0b\x61mount_from\x18\x03 \x01(\x04\x12\x0c\n\x04rate\x18\x04 \x01(\x04\x12\x16\n\x0emin_bid_amount\x18\x05 \x01(\x04\x12\x12\n\ntime_valid\x18\x06 \x01(\x04\x12\x33\n\tlock_type\x18\x07 \x01(\x0e\x32 .basicswap.OfferMessage.LockType\x12\x12\n\nlock_value\x18\x08 \x01(\r\x12\x11\n\tswap_type\x18\t \x01(\r\x12\x15\n\rproof_address\x18\n \x01(\t\x12\x17\n\x0fproof_signature\x18\x0b \x01(\t\x12\x15\n\rpkhash_seller\x18\x0c \x01(\x0c\x12\x13\n\x0bsecret_hash\x18\r \x01(\x0c\x12\x15\n\rfee_rate_from\x18\x0e \x01(\x04\x12\x13\n\x0b\x66\x65\x65_rate_to\x18\x0f \x01(\x04\"q\n\x08LockType\x12\x0b\n\x07NOT_SET\x10\x00\x12\x18\n\x14SEQUENCE_LOCK_BLOCKS\x10\x01\x12\x16\n\x12SEQUENCE_LOCK_TIME\x10\x02\x12\x13\n\x0f\x41\x42S_LOCK_BLOCKS\x10\x03\x12\x11\n\rABS_LOCK_TIME\x10\x04\"\x8c\x01\n\nBidMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x12\n\ntime_valid\x18\x02 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\x12\x14\n\x0cpkhash_buyer\x18\x04 \x01(\x0c\x12\x15\n\rproof_address\x18\x05 \x01(\t\x12\x17\n\x0fproof_signature\x18\x06 \x01(\t\"V\n\x10\x42idAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x15\n\rinitiate_txid\x18\x02 \x01(\x0c\x12\x17\n\x0f\x63ontract_script\x18\x03 \x01(\x0c\"=\n\x12OfferRevokeMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x11\n\tsignature\x18\x02 \x01(\x0c\"\x8a\x01\n\rXmrBidMessage\x12\x14\n\x0coffer_msg_id\x18\x01 \x01(\x0c\x12\x12\n\ntime_valid\x18\x02 \x01(\x04\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\x12\x0c\n\x04pkaf\x18\x04 \x01(\x0c\x12\x0c\n\x04kbvf\x18\x05 \x01(\x0c\x12\x12\n\nkbsf_dleag\x18\x06 \x01(\x0c\x12\x0f\n\x07\x64\x65st_af\x18\x07 \x01(\x0c\"T\n\x0fXmrSplitMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x10\n\x08msg_type\x18\x02 \x01(\r\x12\x10\n\x08sequence\x18\x03 \x01(\r\x12\r\n\x05\x64leag\x18\x04 \x01(\x0c\"\x80\x02\n\x13XmrBidAcceptMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x0c\n\x04pkal\x18\x03 \x01(\x0c\x12\x0c\n\x04kbvl\x18\x04 \x01(\x0c\x12\x12\n\nkbsl_dleag\x18\x05 \x01(\x0c\x12\x11\n\ta_lock_tx\x18\x06 \x01(\x0c\x12\x18\n\x10\x61_lock_tx_script\x18\x07 \x01(\x0c\x12\x18\n\x10\x61_lock_refund_tx\x18\x08 \x01(\x0c\x12\x1f\n\x17\x61_lock_refund_tx_script\x18\t \x01(\x0c\x12\x1e\n\x16\x61_lock_refund_spend_tx\x18\n \x01(\x0c\x12\x1d\n\x15\x61l_lock_refund_tx_sig\x18\x0b \x01(\x0c\"r\n\x17XmrBidLockTxSigsMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12$\n\x1c\x61\x66_lock_refund_spend_tx_esig\x18\x02 \x01(\x0c\x12\x1d\n\x15\x61\x66_lock_refund_tx_sig\x18\x03 \x01(\x0c\"X\n\x18XmrBidLockSpendTxMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x17\n\x0f\x61_lock_spend_tx\x18\x02 \x01(\x0c\x12\x0f\n\x07kal_sig\x18\x03 \x01(\x0c\"M\n\x18XmrBidLockReleaseMessage\x12\x12\n\nbid_msg_id\x18\x01 \x01(\x0c\x12\x1d\n\x15\x61l_lock_spend_tx_esig\x18\x02 \x01(\x0c\x62\x06proto3' ) @@ -385,33 +385,26 @@ _XMRBIDMESSAGE = _descriptor.Descriptor( is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='pkarf', full_name='basicswap.XmrBidMessage.pkarf', index=4, + name='kbvf', full_name='basicswap.XmrBidMessage.kbvf', index=4, number=5, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='kbvf', full_name='basicswap.XmrBidMessage.kbvf', index=5, + name='kbsf_dleag', full_name='basicswap.XmrBidMessage.kbsf_dleag', index=5, number=6, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='kbsf_dleag', full_name='basicswap.XmrBidMessage.kbsf_dleag', index=6, + name='dest_af', full_name='basicswap.XmrBidMessage.dest_af', index=6, number=7, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='dest_af', full_name='basicswap.XmrBidMessage.dest_af', index=7, - number=8, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=b"", - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], @@ -425,7 +418,7 @@ _XMRBIDMESSAGE = _descriptor.Descriptor( oneofs=[ ], serialized_start=799, - serialized_end=952, + serialized_end=937, ) @@ -477,8 +470,8 @@ _XMRSPLITMESSAGE = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=954, - serialized_end=1038, + serialized_start=939, + serialized_end=1023, ) @@ -498,82 +491,68 @@ _XMRBIDACCEPTMESSAGE = _descriptor.Descriptor( is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='sh', full_name='basicswap.XmrBidAcceptMessage.sh', index=1, - number=2, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=b"", - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='pkal', full_name='basicswap.XmrBidAcceptMessage.pkal', index=2, + name='pkal', full_name='basicswap.XmrBidAcceptMessage.pkal', index=1, number=3, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='pkarl', full_name='basicswap.XmrBidAcceptMessage.pkarl', index=3, + name='kbvl', full_name='basicswap.XmrBidAcceptMessage.kbvl', index=2, number=4, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='kbvl', full_name='basicswap.XmrBidAcceptMessage.kbvl', index=4, + name='kbsl_dleag', full_name='basicswap.XmrBidAcceptMessage.kbsl_dleag', index=3, number=5, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='kbsl_dleag', full_name='basicswap.XmrBidAcceptMessage.kbsl_dleag', index=5, + name='a_lock_tx', full_name='basicswap.XmrBidAcceptMessage.a_lock_tx', index=4, number=6, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='a_lock_tx', full_name='basicswap.XmrBidAcceptMessage.a_lock_tx', index=6, + name='a_lock_tx_script', full_name='basicswap.XmrBidAcceptMessage.a_lock_tx_script', index=5, number=7, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='a_lock_tx_script', full_name='basicswap.XmrBidAcceptMessage.a_lock_tx_script', index=7, + name='a_lock_refund_tx', full_name='basicswap.XmrBidAcceptMessage.a_lock_refund_tx', index=6, number=8, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='a_lock_refund_tx', full_name='basicswap.XmrBidAcceptMessage.a_lock_refund_tx', index=8, + name='a_lock_refund_tx_script', full_name='basicswap.XmrBidAcceptMessage.a_lock_refund_tx_script', index=7, number=9, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='a_lock_refund_tx_script', full_name='basicswap.XmrBidAcceptMessage.a_lock_refund_tx_script', index=9, + name='a_lock_refund_spend_tx', full_name='basicswap.XmrBidAcceptMessage.a_lock_refund_spend_tx', index=8, number=10, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='a_lock_refund_spend_tx', full_name='basicswap.XmrBidAcceptMessage.a_lock_refund_spend_tx', index=10, + name='al_lock_refund_tx_sig', full_name='basicswap.XmrBidAcceptMessage.al_lock_refund_tx_sig', index=9, number=11, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='al_lock_refund_tx_sig', full_name='basicswap.XmrBidAcceptMessage.al_lock_refund_tx_sig', index=11, - number=12, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=b"", - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], @@ -586,8 +565,8 @@ _XMRBIDACCEPTMESSAGE = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1041, - serialized_end=1324, + serialized_start=1026, + serialized_end=1282, ) @@ -632,8 +611,8 @@ _XMRBIDLOCKTXSIGSMESSAGE = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1326, - serialized_end=1440, + serialized_start=1284, + serialized_end=1398, ) @@ -660,7 +639,7 @@ _XMRBIDLOCKSPENDTXMESSAGE = _descriptor.Descriptor( is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='al_lock_spend_tx_esig', full_name='basicswap.XmrBidLockSpendTxMessage.al_lock_spend_tx_esig', index=2, + name='kal_sig', full_name='basicswap.XmrBidLockSpendTxMessage.kal_sig', index=2, number=3, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, @@ -678,28 +657,28 @@ _XMRBIDLOCKSPENDTXMESSAGE = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1442, - serialized_end=1544, + serialized_start=1400, + serialized_end=1488, ) -_XMRBIDSECRETMESSAGE = _descriptor.Descriptor( - name='XmrBidSecretMessage', - full_name='basicswap.XmrBidSecretMessage', +_XMRBIDLOCKRELEASEMESSAGE = _descriptor.Descriptor( + name='XmrBidLockReleaseMessage', + full_name='basicswap.XmrBidLockReleaseMessage', filename=None, file=DESCRIPTOR, containing_type=None, create_key=_descriptor._internal_create_key, fields=[ _descriptor.FieldDescriptor( - name='bid_msg_id', full_name='basicswap.XmrBidSecretMessage.bid_msg_id', index=0, + name='bid_msg_id', full_name='basicswap.XmrBidLockReleaseMessage.bid_msg_id', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='secret_value', full_name='basicswap.XmrBidSecretMessage.secret_value', index=1, + name='al_lock_spend_tx_esig', full_name='basicswap.XmrBidLockReleaseMessage.al_lock_spend_tx_esig', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, @@ -717,8 +696,8 @@ _XMRBIDSECRETMESSAGE = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1546, - serialized_end=1609, + serialized_start=1490, + serialized_end=1567, ) _OFFERMESSAGE.fields_by_name['lock_type'].enum_type = _OFFERMESSAGE_LOCKTYPE @@ -732,7 +711,7 @@ DESCRIPTOR.message_types_by_name['XmrSplitMessage'] = _XMRSPLITMESSAGE DESCRIPTOR.message_types_by_name['XmrBidAcceptMessage'] = _XMRBIDACCEPTMESSAGE DESCRIPTOR.message_types_by_name['XmrBidLockTxSigsMessage'] = _XMRBIDLOCKTXSIGSMESSAGE DESCRIPTOR.message_types_by_name['XmrBidLockSpendTxMessage'] = _XMRBIDLOCKSPENDTXMESSAGE -DESCRIPTOR.message_types_by_name['XmrBidSecretMessage'] = _XMRBIDSECRETMESSAGE +DESCRIPTOR.message_types_by_name['XmrBidLockReleaseMessage'] = _XMRBIDLOCKRELEASEMESSAGE _sym_db.RegisterFileDescriptor(DESCRIPTOR) OfferMessage = _reflection.GeneratedProtocolMessageType('OfferMessage', (_message.Message,), { @@ -798,12 +777,12 @@ XmrBidLockSpendTxMessage = _reflection.GeneratedProtocolMessageType('XmrBidLockS }) _sym_db.RegisterMessage(XmrBidLockSpendTxMessage) -XmrBidSecretMessage = _reflection.GeneratedProtocolMessageType('XmrBidSecretMessage', (_message.Message,), { - 'DESCRIPTOR' : _XMRBIDSECRETMESSAGE, +XmrBidLockReleaseMessage = _reflection.GeneratedProtocolMessageType('XmrBidLockReleaseMessage', (_message.Message,), { + 'DESCRIPTOR' : _XMRBIDLOCKRELEASEMESSAGE, '__module__' : 'messages_pb2' - # @@protoc_insertion_point(class_scope:basicswap.XmrBidSecretMessage) + # @@protoc_insertion_point(class_scope:basicswap.XmrBidLockReleaseMessage) }) -_sym_db.RegisterMessage(XmrBidSecretMessage) +_sym_db.RegisterMessage(XmrBidLockReleaseMessage) # @@protoc_insertion_point(module_scope) diff --git a/tests/basicswap/test_other.py b/tests/basicswap/test_other.py index ec1550b..8cf3f50 100644 --- a/tests/basicswap/test_other.py +++ b/tests/basicswap/test_other.py @@ -182,6 +182,16 @@ class Test(unittest.TestCase): assert(vk_encrypt == recovered_key) + def test_sign_compact(self): + coin_settings = {'rpcport': 0, 'rpcauth': 'none', 'blocks_confirmed': 1, 'conf_target': 1} + ci = BTCInterface(coin_settings, 'regtest') + + vk = i2b(ci.getNewSecretKey()) + pk = ci.getPubkey(vk) + sig = ci.signCompact(vk, 'test signing message') + assert(len(sig) == 64) + ci.verifyCompact(pk, 'test signing message', sig) + def test_dleag(self): coin_settings = {'rpcport': 0, 'walletrpcport': 0, 'walletrpcauth': 'none', 'blocks_confirmed': 1, 'conf_target': 1} ci = XMRInterface(coin_settings, 'regtest')