Check for duplicate pubkeys.
Add test for 'non-BIP68-final'.
This commit is contained in:
parent
4bde19fe33
commit
645571e47c
@ -36,7 +36,6 @@ from .util import (
|
||||
format_amount,
|
||||
encodeAddress,
|
||||
decodeAddress,
|
||||
SerialiseNum,
|
||||
DeserialiseNum,
|
||||
decodeWif,
|
||||
toWIF,
|
||||
@ -80,10 +79,14 @@ from .db import (
|
||||
XmrSwap,
|
||||
XmrSplitData,
|
||||
)
|
||||
|
||||
from .explorers import ExplorerInsight, ExplorerBitAps, ExplorerChainz
|
||||
import basicswap.config as cfg
|
||||
from .base import BaseApp
|
||||
from .explorers import (
|
||||
ExplorerInsight,
|
||||
ExplorerBitAps,
|
||||
ExplorerChainz,
|
||||
)
|
||||
import basicswap.config as cfg
|
||||
import basicswap.protocols.atomic_swap_1 as atomic_swap_1
|
||||
|
||||
|
||||
MIN_OFFER_VALID_TIME = 60 * 10
|
||||
@ -348,37 +351,6 @@ def decodeSequence(lock_value):
|
||||
return lock_value & SEQUENCE_LOCKTIME_MASK
|
||||
|
||||
|
||||
def buildContractScript(lock_val, secret_hash, pkh_redeem, pkh_refund, op_lock=OpCodes.OP_CHECKSEQUENCEVERIFY):
|
||||
script = bytearray([
|
||||
OpCodes.OP_IF,
|
||||
OpCodes.OP_SIZE,
|
||||
0x01, 0x20, # 32
|
||||
OpCodes.OP_EQUALVERIFY,
|
||||
OpCodes.OP_SHA256,
|
||||
0x20]) \
|
||||
+ secret_hash \
|
||||
+ bytearray([
|
||||
OpCodes.OP_EQUALVERIFY,
|
||||
OpCodes.OP_DUP,
|
||||
OpCodes.OP_HASH160,
|
||||
0x14]) \
|
||||
+ pkh_redeem \
|
||||
+ bytearray([OpCodes.OP_ELSE, ]) \
|
||||
+ SerialiseNum(lock_val) \
|
||||
+ bytearray([
|
||||
op_lock,
|
||||
OpCodes.OP_DROP,
|
||||
OpCodes.OP_DUP,
|
||||
OpCodes.OP_HASH160,
|
||||
0x14]) \
|
||||
+ pkh_refund \
|
||||
+ bytearray([
|
||||
OpCodes.OP_ENDIF,
|
||||
OpCodes.OP_EQUALVERIFY,
|
||||
OpCodes.OP_CHECKSIG])
|
||||
return script
|
||||
|
||||
|
||||
def extractScriptSecretHash(script):
|
||||
return script[7:39]
|
||||
|
||||
@ -748,7 +720,7 @@ class BasicSwap(BaseApp):
|
||||
self.db_version = db_version
|
||||
kv = session.query(DBKVInt).filter_by(key='db_version').first()
|
||||
if not kv:
|
||||
kv = DBKVInt(key=str_key, value=db_version)
|
||||
kv = DBKVInt(key='db_version', value=db_version)
|
||||
else:
|
||||
kv.value = db_version
|
||||
session.add(kv)
|
||||
@ -1658,14 +1630,14 @@ class BasicSwap(BaseApp):
|
||||
else:
|
||||
if offer.lock_type < ABS_LOCK_BLOCKS:
|
||||
sequence = getExpectedSequence(offer.lock_type, offer.lock_value, coin_from)
|
||||
script = buildContractScript(sequence, secret_hash, bid.pkhash_buyer, pkhash_refund)
|
||||
script = atomic_swap_1.buildContractScript(sequence, secret_hash, bid.pkhash_buyer, pkhash_refund)
|
||||
else:
|
||||
if offer.lock_type == ABS_LOCK_BLOCKS:
|
||||
lock_value = self.callcoinrpc(coin_from, 'getblockchaininfo')['blocks'] + offer.lock_value
|
||||
else:
|
||||
lock_value = int(time.time()) + offer.lock_value
|
||||
self.log.debug('Initiate %s lock_value %d %d', coin_from, offer.lock_value, lock_value)
|
||||
script = buildContractScript(lock_value, secret_hash, bid.pkhash_buyer, pkhash_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
|
||||
script = atomic_swap_1.buildContractScript(lock_value, secret_hash, bid.pkhash_buyer, pkhash_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
|
||||
|
||||
p2sh = self.callcoinrpc(Coins.PART, 'decodescript', [script.hex()])['p2sh']
|
||||
|
||||
@ -2061,7 +2033,7 @@ class BasicSwap(BaseApp):
|
||||
lock_value = offer.lock_value // 2
|
||||
if offer.lock_type < ABS_LOCK_BLOCKS:
|
||||
sequence = getExpectedSequence(offer.lock_type, lock_value, coin_to)
|
||||
participate_script = buildContractScript(sequence, secret_hash, pkhash_seller, pkhash_buyer_refund)
|
||||
participate_script = atomic_swap_1.buildContractScript(sequence, secret_hash, pkhash_seller, pkhash_buyer_refund)
|
||||
else:
|
||||
# Lock from the height or time of the block containing the initiate txn
|
||||
coin_from = Coins(offer.coin_from)
|
||||
@ -2092,7 +2064,7 @@ class BasicSwap(BaseApp):
|
||||
self.log.debug('Setting lock value from time of block %s %s', coin_from, initiate_tx_block_hash)
|
||||
contract_lock_value = initiate_tx_block_time + lock_value
|
||||
self.log.debug('participate %s lock_value %d %d', coin_to, lock_value, contract_lock_value)
|
||||
participate_script = buildContractScript(contract_lock_value, secret_hash, pkhash_seller, pkhash_buyer_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
|
||||
participate_script = atomic_swap_1.buildContractScript(contract_lock_value, secret_hash, pkhash_seller, pkhash_buyer_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
|
||||
return participate_script
|
||||
|
||||
def createParticipateTxn(self, bid_id, bid, offer, participate_script):
|
||||
@ -3630,6 +3602,15 @@ class BasicSwap(BaseApp):
|
||||
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.')
|
||||
if xmr_swap.pkbsl == xmr_swap.pkbsf:
|
||||
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)
|
||||
|
||||
|
@ -19,13 +19,14 @@ class ECCParameters():
|
||||
self.o = o
|
||||
|
||||
|
||||
ep = ECCParameters( \
|
||||
p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f, \
|
||||
a = 0x0, \
|
||||
b = 0x7, \
|
||||
Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, \
|
||||
Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8, \
|
||||
o = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141) # noqa: E221,E251,E502
|
||||
ep = ECCParameters(
|
||||
p=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,
|
||||
a=0x0,
|
||||
b=0x7,
|
||||
Gx=0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
|
||||
Gy=0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8,
|
||||
o=0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141)
|
||||
|
||||
|
||||
curve_secp256k1 = CurveFp(ep.p, ep.a, ep.b)
|
||||
G = Point(curve_secp256k1, ep.Gx, ep.Gy, ep.o)
|
||||
|
@ -670,7 +670,7 @@ class BTCInterface(CoinInterface):
|
||||
assert_cond(tx.vin[0].prevout.hash == b2i(lock_tx_id) and tx.vin[0].prevout.n == locked_n, 'Input prevout mismatch')
|
||||
|
||||
assert_cond(len(tx.vout) == 1, 'tx doesn\'t have one output')
|
||||
p2wpkh = self.getScriptForPubkeyHash(a_pkhash_f)
|
||||
p2wpkh = self.getScriptForPubkeyHash(a_pkhash_f)
|
||||
assert_cond(tx.vout[0].scriptPubKey == p2wpkh, 'Bad output destination')
|
||||
|
||||
fee_paid = locked_coin - tx.vout[0].nValue
|
||||
|
@ -159,6 +159,8 @@ class XMRInterface(CoinInterface):
|
||||
return(i < edf.l and i > 8)
|
||||
|
||||
def verifyPubkey(self, pubkey_bytes):
|
||||
# Calls ed25519_decode_check_point() in secp256k1
|
||||
# Checks for small order
|
||||
return verify_ed25519_point(pubkey_bytes)
|
||||
|
||||
def proveDLEAG(self, key):
|
||||
@ -240,13 +242,13 @@ class XMRInterface(CoinInterface):
|
||||
except Exception as e:
|
||||
logging.info('rpc_cb failed %s', str(e))
|
||||
current_height = None # If the transfer is available it will be deep enough
|
||||
# and (current_height is None or current_height - transfer['block_height'] > cb_block_confirmed):
|
||||
'''
|
||||
params = {'transfer_type': 'available'}
|
||||
rv = self.rpc_wallet_cb('incoming_transfers', params)
|
||||
if 'transfers' in rv:
|
||||
for transfer in rv['transfers']:
|
||||
if transfer['amount'] == cb_swap_value:
|
||||
# and (current_height is None or current_height - transfer['block_height'] > cb_block_confirmed):
|
||||
return {'txid': transfer['tx_hash'], 'amount': transfer['amount'], 'height': 0 if 'block_height' not in transfer else transfer['block_height']}
|
||||
else:
|
||||
logging.warning('Incorrect amount detected for coin b lock txn: {}'.format(transfer['tx_hash']))
|
||||
|
0
basicswap/protocols/__init__.py
Normal file
0
basicswap/protocols/__init__.py
Normal file
43
basicswap/protocols/atomic_swap_1.py
Normal file
43
basicswap/protocols/atomic_swap_1.py
Normal file
@ -0,0 +1,43 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
from basicswap.util import (
|
||||
SerialiseNum,
|
||||
)
|
||||
from basicswap.script import (
|
||||
OpCodes,
|
||||
)
|
||||
|
||||
|
||||
def buildContractScript(lock_val, secret_hash, pkh_redeem, pkh_refund, op_lock=OpCodes.OP_CHECKSEQUENCEVERIFY):
|
||||
script = bytearray([
|
||||
OpCodes.OP_IF,
|
||||
OpCodes.OP_SIZE,
|
||||
0x01, 0x20, # 32
|
||||
OpCodes.OP_EQUALVERIFY,
|
||||
OpCodes.OP_SHA256,
|
||||
0x20]) \
|
||||
+ secret_hash \
|
||||
+ bytearray([
|
||||
OpCodes.OP_EQUALVERIFY,
|
||||
OpCodes.OP_DUP,
|
||||
OpCodes.OP_HASH160,
|
||||
0x14]) \
|
||||
+ pkh_redeem \
|
||||
+ bytearray([OpCodes.OP_ELSE, ]) \
|
||||
+ SerialiseNum(lock_val) \
|
||||
+ bytearray([
|
||||
op_lock,
|
||||
OpCodes.OP_DROP,
|
||||
OpCodes.OP_DUP,
|
||||
OpCodes.OP_HASH160,
|
||||
0x14]) \
|
||||
+ pkh_refund \
|
||||
+ bytearray([
|
||||
OpCodes.OP_ENDIF,
|
||||
OpCodes.OP_EQUALVERIFY,
|
||||
OpCodes.OP_CHECKSIG])
|
||||
return script
|
5
basicswap/protocols/xmr_swap_1.py
Normal file
5
basicswap/protocols/xmr_swap_1.py
Normal file
@ -0,0 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
@ -760,6 +760,36 @@ class Test(unittest.TestCase):
|
||||
self.wait_for_bid(swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
|
||||
self.wait_for_bid(swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True)
|
||||
|
||||
def test_10_locked_refundtx(self):
|
||||
logging.info('---------- Test Refund tx is locked')
|
||||
swap_clients = self.swap_clients
|
||||
offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.XMR, 10 * COIN, 100 * XMR_COIN, 10 * COIN, SwapTypes.XMR_SWAP)
|
||||
self.wait_for_offer(swap_clients[1], offer_id)
|
||||
offers = swap_clients[1].listOffers(filters={'offer_id': offer_id})
|
||||
offer = offers[0]
|
||||
|
||||
bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from)
|
||||
|
||||
self.wait_for_bid(swap_clients[0], bid_id, BidStates.BID_RECEIVED)
|
||||
|
||||
bid, xmr_swap = swap_clients[0].getXmrBid(bid_id)
|
||||
assert(xmr_swap)
|
||||
|
||||
swap_clients[1].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK)
|
||||
|
||||
swap_clients[0].acceptXmrBid(bid_id)
|
||||
|
||||
self.wait_for_bid(swap_clients[0], bid_id, BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED, wait_for=180)
|
||||
|
||||
bid, xmr_swap = swap_clients[0].getXmrBid(bid_id)
|
||||
assert(xmr_swap)
|
||||
|
||||
try:
|
||||
swap_clients[0].ci(Coins.BTC).publishTx(xmr_swap.a_lock_refund_tx)
|
||||
assert(False), 'Lock refund tx should be locked'
|
||||
except Exception as e:
|
||||
assert('non-BIP68-final' in str(e))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
Reference in New Issue
Block a user