Host-customized fork of https://github.com/tecnovert/basicswap/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
3.1 KiB
100 lines
3.1 KiB
# -*- coding: utf-8 -*- |
|
|
|
# Copyright (c) 2020-2023 tecnovert |
|
# Distributed under the MIT software license, see the accompanying |
|
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. |
|
|
|
from basicswap.db import ( |
|
Concepts, |
|
) |
|
from basicswap.util import ( |
|
SerialiseNum, |
|
) |
|
from basicswap.script import ( |
|
OpCodes, |
|
) |
|
from basicswap.basicswap_util import ( |
|
SwapTypes, |
|
EventLogTypes, |
|
) |
|
from . import ProtocolInterface |
|
|
|
INITIATE_TX_TIMEOUT = 40 * 60 # TODO: make variable per coin |
|
ABS_LOCK_TIME_LEEWAY = 10 * 60 |
|
|
|
|
|
def buildContractScript(lock_val: int, secret_hash: bytes, pkh_redeem: bytes, pkh_refund: bytes, op_lock=OpCodes.OP_CHECKSEQUENCEVERIFY) -> bytearray: |
|
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] |
|
|
|
|
|
def redeemITx(self, bid_id: bytes, session): |
|
bid, offer = self.getBidAndOffer(bid_id, session) |
|
ci_from = self.ci(offer.coin_from) |
|
|
|
txn = self.createRedeemTxn(ci_from.coin_type(), bid, for_txn_type='initiate') |
|
txid = ci_from.publishTx(bytes.fromhex(txn)) |
|
|
|
bid.initiate_tx.spend_txid = bytes.fromhex(txid) |
|
self.log.debug('Submitted initiate redeem txn %s to %s chain for bid %s', txid, ci_from.coin_name(), bid_id.hex()) |
|
self.logEvent(Concepts.BID, bid_id, EventLogTypes.ITX_REDEEM_PUBLISHED, '', session) |
|
|
|
|
|
class AtomicSwapInterface(ProtocolInterface): |
|
swap_type = SwapTypes.SELLER_FIRST |
|
|
|
def getFundedInitiateTxTemplate(self, ci, amount: int, sub_fee: bool) -> bytes: |
|
addr_to = self.getMockAddrTo(ci) |
|
funded_tx = ci.createRawFundedTransaction(addr_to, amount, sub_fee, lock_unspents=False) |
|
|
|
return bytes.fromhex(funded_tx) |
|
|
|
def promoteMockTx(self, ci, mock_tx: bytes, script: bytearray) -> bytearray: |
|
mock_txo_script = self.getMockScriptScriptPubkey(ci) |
|
real_txo_script = ci.get_p2wsh_script_pubkey(script) if ci._use_segwit else ci.get_p2sh_script_pubkey(script) |
|
|
|
found: int = 0 |
|
ctx = ci.loadTx(mock_tx) |
|
for txo in ctx.vout: |
|
if txo.scriptPubKey == mock_txo_script: |
|
txo.scriptPubKey = real_txo_script |
|
found += 1 |
|
|
|
if found < 1: |
|
raise ValueError('Mocked output not found') |
|
if found > 1: |
|
raise ValueError('Too many mocked outputs found') |
|
ctx.nLockTime = 0 |
|
|
|
funded_tx = ctx.serialize() |
|
return ci.signTxWithWallet(funded_tx)
|
|
|