Poll chainstates.
Litecoin download link changed. Fix fee comparison tx weight difference. Remove format8. New stalled for test bid state. Moved sequence code to coin interfaces. Display estimated time lock refund tx will be valid.
This commit is contained in:
parent
c66160fb09
commit
deb71856e8
@ -16,6 +16,7 @@ import struct
|
|||||||
import hashlib
|
import hashlib
|
||||||
import secrets
|
import secrets
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
import collections
|
import collections
|
||||||
@ -33,7 +34,6 @@ from .interface_bitcore_btc import BitcoreBTCInterface
|
|||||||
from . import __version__
|
from . import __version__
|
||||||
from .util import (
|
from .util import (
|
||||||
pubkeyToAddress,
|
pubkeyToAddress,
|
||||||
format8,
|
|
||||||
format_amount,
|
format_amount,
|
||||||
format_timestamp,
|
format_timestamp,
|
||||||
encodeAddress,
|
encodeAddress,
|
||||||
@ -89,6 +89,11 @@ from .explorers import (
|
|||||||
ExplorerBitAps,
|
ExplorerBitAps,
|
||||||
ExplorerChainz,
|
ExplorerChainz,
|
||||||
)
|
)
|
||||||
|
from .types import (
|
||||||
|
SEQUENCE_LOCK_BLOCKS,
|
||||||
|
SEQUENCE_LOCK_TIME,
|
||||||
|
ABS_LOCK_BLOCKS,
|
||||||
|
ABS_LOCK_TIME)
|
||||||
import basicswap.config as cfg
|
import basicswap.config as cfg
|
||||||
import basicswap.network as bsn
|
import basicswap.network as bsn
|
||||||
import basicswap.protocols.atomic_swap_1 as atomic_swap_1
|
import basicswap.protocols.atomic_swap_1 as atomic_swap_1
|
||||||
@ -152,6 +157,7 @@ class BidStates(IntEnum):
|
|||||||
SWAP_TIMEDOUT = auto()
|
SWAP_TIMEDOUT = auto()
|
||||||
BID_ABANDONED = auto() # Bid will no longer be processed
|
BID_ABANDONED = auto() # Bid will no longer be processed
|
||||||
BID_ERROR = auto() # An error occurred
|
BID_ERROR = auto() # An error occurred
|
||||||
|
BID_STALLED_FOR_TEST = auto()
|
||||||
|
|
||||||
|
|
||||||
class TxStates(IntEnum):
|
class TxStates(IntEnum):
|
||||||
@ -221,14 +227,6 @@ class DebugTypes(IntEnum):
|
|||||||
MAKE_INVALID_PTX = auto()
|
MAKE_INVALID_PTX = auto()
|
||||||
|
|
||||||
|
|
||||||
SEQUENCE_LOCK_BLOCKS = 1
|
|
||||||
SEQUENCE_LOCK_TIME = 2
|
|
||||||
ABS_LOCK_BLOCKS = 3
|
|
||||||
ABS_LOCK_TIME = 4
|
|
||||||
|
|
||||||
SEQUENCE_LOCKTIME_GRANULARITY = 9 # 512 seconds
|
|
||||||
SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22)
|
|
||||||
SEQUENCE_LOCKTIME_MASK = 0x0000ffff
|
|
||||||
INITIATE_TX_TIMEOUT = 40 * 60 # TODO: make variable per coin
|
INITIATE_TX_TIMEOUT = 40 * 60 # TODO: make variable per coin
|
||||||
|
|
||||||
|
|
||||||
@ -263,6 +261,8 @@ def strBidState(state):
|
|||||||
return 'Timed-out'
|
return 'Timed-out'
|
||||||
if state == BidStates.BID_ABANDONED:
|
if state == BidStates.BID_ABANDONED:
|
||||||
return 'Abandoned'
|
return 'Abandoned'
|
||||||
|
if state == BidStates.BID_STALLED_FOR_TEST:
|
||||||
|
return 'Stalled (debug)'
|
||||||
if state == BidStates.BID_ERROR:
|
if state == BidStates.BID_ERROR:
|
||||||
return 'Error'
|
return 'Error'
|
||||||
if state == BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED:
|
if state == BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED:
|
||||||
@ -366,27 +366,6 @@ def describeEventEntry(event_type, event_msg):
|
|||||||
return 'Lock tx B refund tx published'
|
return 'Lock tx B refund tx published'
|
||||||
|
|
||||||
|
|
||||||
def getExpectedSequence(lockType, lockVal, coin_type):
|
|
||||||
assert(lockVal >= 1), 'Bad lockVal'
|
|
||||||
if lockType == SEQUENCE_LOCK_BLOCKS:
|
|
||||||
return lockVal
|
|
||||||
if lockType == SEQUENCE_LOCK_TIME:
|
|
||||||
secondsLocked = lockVal
|
|
||||||
# Ensure the locked time is never less than lockVal
|
|
||||||
if secondsLocked % (1 << SEQUENCE_LOCKTIME_GRANULARITY) != 0:
|
|
||||||
secondsLocked += (1 << SEQUENCE_LOCKTIME_GRANULARITY)
|
|
||||||
secondsLocked >>= SEQUENCE_LOCKTIME_GRANULARITY
|
|
||||||
return secondsLocked | SEQUENCE_LOCKTIME_TYPE_FLAG
|
|
||||||
raise ValueError('Unknown lock type')
|
|
||||||
|
|
||||||
|
|
||||||
def decodeSequence(lock_value):
|
|
||||||
# Return the raw value
|
|
||||||
if lock_value & SEQUENCE_LOCKTIME_TYPE_FLAG:
|
|
||||||
return (lock_value & SEQUENCE_LOCKTIME_MASK) << SEQUENCE_LOCKTIME_GRANULARITY
|
|
||||||
return lock_value & SEQUENCE_LOCKTIME_MASK
|
|
||||||
|
|
||||||
|
|
||||||
def getVoutByAddress(txjs, p2sh):
|
def getVoutByAddress(txjs, p2sh):
|
||||||
for o in txjs['vout']:
|
for o in txjs['vout']:
|
||||||
try:
|
try:
|
||||||
@ -420,6 +399,29 @@ def getOfferProofOfFundsHash(offer_msg, offer_addr):
|
|||||||
return h.digest()
|
return h.digest()
|
||||||
|
|
||||||
|
|
||||||
|
def threadPollChainState(swap_client, coin_type):
|
||||||
|
while not swap_client.delay_event.is_set():
|
||||||
|
try:
|
||||||
|
ci = swap_client.ci(coin_type)
|
||||||
|
if coin_type == Coins.XMR:
|
||||||
|
new_height = ci.getChainHeight()
|
||||||
|
if new_height != swap_client.coin_clients[coin_type]['chain_height']:
|
||||||
|
swap_client.log.debug('New {} block at height: {}'.format(str(coin_type), new_height))
|
||||||
|
with swap_client.mxDB:
|
||||||
|
swap_client.coin_clients[coin_type]['chain_height'] = new_height
|
||||||
|
else:
|
||||||
|
chain_state = ci.getBlockchainInfo()
|
||||||
|
if chain_state['bestblockhash'] != swap_client.coin_clients[coin_type]['chain_best_block']:
|
||||||
|
swap_client.log.debug('New {} block at height: {}'.format(str(coin_type), chain_state['blocks']))
|
||||||
|
with swap_client.mxDB:
|
||||||
|
swap_client.coin_clients[coin_type]['chain_height'] = chain_state['blocks']
|
||||||
|
swap_client.coin_clients[coin_type]['chain_best_block'] = chain_state['bestblockhash']
|
||||||
|
swap_client.coin_clients[coin_type]['chain_median_time'] = chain_state['mediantime']
|
||||||
|
except Exception as e:
|
||||||
|
swap_client.log.warning('threadPollChainState error: {}'.format(str(e)))
|
||||||
|
swap_client.delay_event.wait(random.randrange(20, 30)) # random to stagger updates
|
||||||
|
|
||||||
|
|
||||||
class WatchedOutput(): # Watch for spends
|
class WatchedOutput(): # Watch for spends
|
||||||
__slots__ = ('bid_id', 'txid_hex', 'vout', 'tx_type', 'swap_type')
|
__slots__ = ('bid_id', 'txid_hex', 'vout', 'tx_type', 'swap_type')
|
||||||
|
|
||||||
@ -476,6 +478,9 @@ class BasicSwap(BaseApp):
|
|||||||
|
|
||||||
self.SMSG_SECONDS_IN_HOUR = 60 * 2 if self.chain == 'regtest' else 60 * 60
|
self.SMSG_SECONDS_IN_HOUR = 60 * 2 if self.chain == 'regtest' else 60 * 60
|
||||||
|
|
||||||
|
self.delay_event = threading.Event()
|
||||||
|
self.threads = []
|
||||||
|
|
||||||
# Encode key to match network
|
# Encode key to match network
|
||||||
wif_prefix = chainparams[Coins.PART][self.chain]['key_prefix']
|
wif_prefix = chainparams[Coins.PART][self.chain]['key_prefix']
|
||||||
self.network_key = toWIF(wif_prefix, decodeWif(self.settings['network_key']))
|
self.network_key = toWIF(wif_prefix, decodeWif(self.settings['network_key']))
|
||||||
@ -551,11 +556,15 @@ class BasicSwap(BaseApp):
|
|||||||
|
|
||||||
with self.mxDB:
|
with self.mxDB:
|
||||||
self.is_running = False
|
self.is_running = False
|
||||||
|
self.delay_event.set()
|
||||||
|
|
||||||
if self._network:
|
if self._network:
|
||||||
self._network.stopNetwork()
|
self._network.stopNetwork()
|
||||||
self._network = None
|
self._network = None
|
||||||
|
|
||||||
|
for t in self.threads:
|
||||||
|
t.join()
|
||||||
|
|
||||||
def setCoinConnectParams(self, coin):
|
def setCoinConnectParams(self, coin):
|
||||||
# Set anything that does not require the daemon to be running
|
# Set anything that does not require the daemon to be running
|
||||||
chain_client_settings = self.getChainClientSettings(coin)
|
chain_client_settings = self.getChainClientSettings(coin)
|
||||||
@ -594,7 +603,6 @@ class BasicSwap(BaseApp):
|
|||||||
'conf_target': chain_client_settings.get('conf_target', 2),
|
'conf_target': chain_client_settings.get('conf_target', 2),
|
||||||
'watched_outputs': [],
|
'watched_outputs': [],
|
||||||
'last_height_checked': last_height_checked,
|
'last_height_checked': last_height_checked,
|
||||||
'last_height': None,
|
|
||||||
'use_segwit': chain_client_settings.get('use_segwit', False),
|
'use_segwit': chain_client_settings.get('use_segwit', False),
|
||||||
'use_csv': chain_client_settings.get('use_csv', True),
|
'use_csv': chain_client_settings.get('use_csv', True),
|
||||||
'core_version_group': chain_client_settings.get('core_version_group', 0),
|
'core_version_group': chain_client_settings.get('core_version_group', 0),
|
||||||
@ -604,6 +612,11 @@ class BasicSwap(BaseApp):
|
|||||||
'chain_lookups': chain_client_settings.get('chain_lookups', 'local'),
|
'chain_lookups': chain_client_settings.get('chain_lookups', 'local'),
|
||||||
'restore_height': chain_client_settings.get('restore_height', 0),
|
'restore_height': chain_client_settings.get('restore_height', 0),
|
||||||
'fee_priority': chain_client_settings.get('fee_priority', 0),
|
'fee_priority': chain_client_settings.get('fee_priority', 0),
|
||||||
|
|
||||||
|
# Chain state
|
||||||
|
'chain_height': None,
|
||||||
|
'chain_best_block': None,
|
||||||
|
'chain_median_time': None,
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.coin_clients[coin]['connection_type'] == 'rpc':
|
if self.coin_clients[coin]['connection_type'] == 'rpc':
|
||||||
@ -697,6 +710,10 @@ class BasicSwap(BaseApp):
|
|||||||
self.log.info('%s Core version %d', ci.coin_name(), core_version)
|
self.log.info('%s Core version %d', ci.coin_name(), core_version)
|
||||||
self.coin_clients[c]['core_version'] = core_version
|
self.coin_clients[c]['core_version'] = core_version
|
||||||
|
|
||||||
|
t = threading.Thread(target=threadPollChainState, args=(self, c))
|
||||||
|
self.threads.append(t)
|
||||||
|
t.start()
|
||||||
|
|
||||||
if c == Coins.PART:
|
if c == Coins.PART:
|
||||||
self.coin_clients[c]['have_spent_index'] = ci.haveSpentIndex()
|
self.coin_clients[c]['have_spent_index'] = ci.haveSpentIndex()
|
||||||
|
|
||||||
@ -1065,10 +1082,12 @@ class BasicSwap(BaseApp):
|
|||||||
assert(coin_from != coin_to), 'coin_from == coin_to'
|
assert(coin_from != coin_to), 'coin_from == coin_to'
|
||||||
try:
|
try:
|
||||||
coin_from_t = Coins(coin_from)
|
coin_from_t = Coins(coin_from)
|
||||||
|
ci_from = self.ci(coin_from_t)
|
||||||
except Exception:
|
except Exception:
|
||||||
raise ValueError('Unknown coin from type')
|
raise ValueError('Unknown coin from type')
|
||||||
try:
|
try:
|
||||||
coin_to_t = Coins(coin_to)
|
coin_to_t = Coins(coin_to)
|
||||||
|
ci_to = self.ci(coin_to_t)
|
||||||
except Exception:
|
except Exception:
|
||||||
raise ValueError('Unknown coin to type')
|
raise ValueError('Unknown coin to type')
|
||||||
|
|
||||||
@ -1124,10 +1143,10 @@ class BasicSwap(BaseApp):
|
|||||||
xmr_offer = XmrOffer()
|
xmr_offer = XmrOffer()
|
||||||
|
|
||||||
# Delay before the chain a lock refund tx can be mined
|
# Delay before the chain a lock refund tx can be mined
|
||||||
xmr_offer.lock_time_1 = getExpectedSequence(lock_type, lock_value, coin_from)
|
xmr_offer.lock_time_1 = ci_from.getExpectedSequence(lock_type, lock_value)
|
||||||
|
|
||||||
# Delay before the follower can spend from the chain a lock refund tx
|
# Delay before the follower can spend from the chain a lock refund tx
|
||||||
xmr_offer.lock_time_2 = getExpectedSequence(lock_type, lock_value, coin_from)
|
xmr_offer.lock_time_2 = ci_from.getExpectedSequence(lock_type, lock_value)
|
||||||
|
|
||||||
xmr_offer.a_fee_rate = msg_buf.fee_rate_from
|
xmr_offer.a_fee_rate = msg_buf.fee_rate_from
|
||||||
xmr_offer.b_fee_rate = msg_buf.fee_rate_to # Unused: TODO - Set priority?
|
xmr_offer.b_fee_rate = msg_buf.fee_rate_to # Unused: TODO - Set priority?
|
||||||
@ -1359,7 +1378,8 @@ class BasicSwap(BaseApp):
|
|||||||
return self.callcoinrpc(coin_type, 'getnetworkinfo')['relayfee']
|
return self.callcoinrpc(coin_type, 'getnetworkinfo')['relayfee']
|
||||||
|
|
||||||
def getFeeRateForCoin(self, coin_type, conf_target=2):
|
def getFeeRateForCoin(self, coin_type, conf_target=2):
|
||||||
override_feerate = self.coin_clients[coin_type].get('override_feerate', None)
|
chain_client_settings = self.getChainClientSettings(coin_type)
|
||||||
|
override_feerate = chain_client_settings.get('override_feerate', None)
|
||||||
if override_feerate:
|
if override_feerate:
|
||||||
self.log.debug('Fee rate override used for %s: %f', str(coin_type), override_feerate)
|
self.log.debug('Fee rate override used for %s: %f', str(coin_type), override_feerate)
|
||||||
return override_feerate, 'override_feerate'
|
return override_feerate, 'override_feerate'
|
||||||
@ -1592,7 +1612,7 @@ class BasicSwap(BaseApp):
|
|||||||
|
|
||||||
def postBid(self, offer_id, amount, addr_send_from=None, extra_options={}):
|
def postBid(self, offer_id, amount, addr_send_from=None, extra_options={}):
|
||||||
# Bid to send bid.amount * offer.rate of coin_to in exchange for bid.amount of coin_from
|
# Bid to send bid.amount * offer.rate of coin_to in exchange for bid.amount of coin_from
|
||||||
self.log.debug('postBid %s %s', offer_id.hex(), format8(amount))
|
self.log.debug('postBid %s', offer_id.hex())
|
||||||
|
|
||||||
offer = self.getOffer(offer_id)
|
offer = self.getOffer(offer_id)
|
||||||
assert(offer), 'Offer not found: {}.'.format(offer_id.hex())
|
assert(offer), 'Offer not found: {}.'.format(offer_id.hex())
|
||||||
@ -1828,6 +1848,7 @@ class BasicSwap(BaseApp):
|
|||||||
bid.contract_count = self.getNewContractId()
|
bid.contract_count = self.getNewContractId()
|
||||||
|
|
||||||
coin_from = Coins(offer.coin_from)
|
coin_from = Coins(offer.coin_from)
|
||||||
|
ci_from = self.ci(coin_from)
|
||||||
bid_date = dt.datetime.fromtimestamp(bid.created_at).date()
|
bid_date = dt.datetime.fromtimestamp(bid.created_at).date()
|
||||||
|
|
||||||
secret = self.getContractSecret(bid_date, bid.contract_count)
|
secret = self.getContractSecret(bid_date, bid.contract_count)
|
||||||
@ -1842,7 +1863,7 @@ class BasicSwap(BaseApp):
|
|||||||
script = bid.initiate_tx.script
|
script = bid.initiate_tx.script
|
||||||
else:
|
else:
|
||||||
if offer.lock_type < ABS_LOCK_BLOCKS:
|
if offer.lock_type < ABS_LOCK_BLOCKS:
|
||||||
sequence = getExpectedSequence(offer.lock_type, offer.lock_value, coin_from)
|
sequence = ci_from.getExpectedSequence(offer.lock_type, offer.lock_value)
|
||||||
script = atomic_swap_1.buildContractScript(sequence, secret_hash, bid.pkhash_buyer, pkhash_refund)
|
script = atomic_swap_1.buildContractScript(sequence, secret_hash, bid.pkhash_buyer, pkhash_refund)
|
||||||
else:
|
else:
|
||||||
if offer.lock_type == ABS_LOCK_BLOCKS:
|
if offer.lock_type == ABS_LOCK_BLOCKS:
|
||||||
@ -1907,7 +1928,7 @@ class BasicSwap(BaseApp):
|
|||||||
def postXmrBid(self, offer_id, amount, addr_send_from=None):
|
def postXmrBid(self, offer_id, amount, addr_send_from=None):
|
||||||
# Bid to send bid.amount * offer.rate of coin_to in exchange for bid.amount of coin_from
|
# Bid to send bid.amount * offer.rate of coin_to in exchange for bid.amount of coin_from
|
||||||
# Send MSG1L F -> L
|
# Send MSG1L F -> L
|
||||||
self.log.debug('postXmrBid %s %s', offer_id.hex(), format8(amount))
|
self.log.debug('postXmrBid %s', offer_id.hex())
|
||||||
|
|
||||||
self.mxDB.acquire()
|
self.mxDB.acquire()
|
||||||
try:
|
try:
|
||||||
@ -2187,13 +2208,14 @@ class BasicSwap(BaseApp):
|
|||||||
def createInitiateTxn(self, coin_type, bid_id, bid, initiate_script):
|
def createInitiateTxn(self, coin_type, bid_id, bid, initiate_script):
|
||||||
if self.coin_clients[coin_type]['connection_type'] != 'rpc':
|
if self.coin_clients[coin_type]['connection_type'] != 'rpc':
|
||||||
return None
|
return None
|
||||||
|
ci = self.ci(coin_type)
|
||||||
|
|
||||||
if self.coin_clients[coin_type]['use_segwit']:
|
if self.coin_clients[coin_type]['use_segwit']:
|
||||||
addr_to = self.encodeSegwitP2WSH(coin_type, getP2WSH(initiate_script))
|
addr_to = self.encodeSegwitP2WSH(coin_type, getP2WSH(initiate_script))
|
||||||
else:
|
else:
|
||||||
addr_to = self.getScriptAddress(coin_type, initiate_script)
|
addr_to = self.getScriptAddress(coin_type, initiate_script)
|
||||||
self.log.debug('Create initiate txn for coin %s to %s for bid %s', str(coin_type), addr_to, bid_id.hex())
|
self.log.debug('Create initiate txn for coin %s to %s for bid %s', str(coin_type), addr_to, bid_id.hex())
|
||||||
txn = self.callcoinrpc(coin_type, 'createrawtransaction', [[], {addr_to: format8(bid.amount)}])
|
txn = self.callcoinrpc(coin_type, 'createrawtransaction', [[], {addr_to: ci.format_amount(bid.amount)}])
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
'lockUnspents': True,
|
'lockUnspents': True,
|
||||||
@ -2207,6 +2229,7 @@ class BasicSwap(BaseApp):
|
|||||||
self.log.debug('deriveParticipateScript for bid %s', bid_id.hex())
|
self.log.debug('deriveParticipateScript for bid %s', bid_id.hex())
|
||||||
|
|
||||||
coin_to = Coins(offer.coin_to)
|
coin_to = Coins(offer.coin_to)
|
||||||
|
ci_to = self.ci(coin_to)
|
||||||
|
|
||||||
bid_date = dt.datetime.fromtimestamp(bid.created_at).date()
|
bid_date = dt.datetime.fromtimestamp(bid.created_at).date()
|
||||||
|
|
||||||
@ -2217,7 +2240,7 @@ class BasicSwap(BaseApp):
|
|||||||
# Participate txn is locked for half the time of the initiate txn
|
# Participate txn is locked for half the time of the initiate txn
|
||||||
lock_value = offer.lock_value // 2
|
lock_value = offer.lock_value // 2
|
||||||
if offer.lock_type < ABS_LOCK_BLOCKS:
|
if offer.lock_type < ABS_LOCK_BLOCKS:
|
||||||
sequence = getExpectedSequence(offer.lock_type, lock_value, coin_to)
|
sequence = ci_to.getExpectedSequence(offer.lock_type, lock_value)
|
||||||
participate_script = atomic_swap_1.buildContractScript(sequence, secret_hash, pkhash_seller, pkhash_buyer_refund)
|
participate_script = atomic_swap_1.buildContractScript(sequence, secret_hash, pkhash_seller, pkhash_buyer_refund)
|
||||||
else:
|
else:
|
||||||
# Lock from the height or time of the block containing the initiate txn
|
# Lock from the height or time of the block containing the initiate txn
|
||||||
@ -2259,6 +2282,7 @@ class BasicSwap(BaseApp):
|
|||||||
|
|
||||||
if self.coin_clients[coin_to]['connection_type'] != 'rpc':
|
if self.coin_clients[coin_to]['connection_type'] != 'rpc':
|
||||||
return None
|
return None
|
||||||
|
ci = self.ci(coin_to)
|
||||||
|
|
||||||
amount_to = bid.amount_to
|
amount_to = bid.amount_to
|
||||||
# Check required?
|
# Check required?
|
||||||
@ -2275,7 +2299,7 @@ class BasicSwap(BaseApp):
|
|||||||
else:
|
else:
|
||||||
addr_to = self.getScriptAddress(coin_to, participate_script)
|
addr_to = self.getScriptAddress(coin_to, participate_script)
|
||||||
|
|
||||||
txn = self.callcoinrpc(coin_to, 'createrawtransaction', [[], {addr_to: format8(amount_to)}])
|
txn = self.callcoinrpc(coin_to, 'createrawtransaction', [[], {addr_to: ci.format_amount(amount_to)}])
|
||||||
options = {
|
options = {
|
||||||
'lockUnspents': True,
|
'lockUnspents': True,
|
||||||
'conf_target': self.coin_clients[coin_to]['conf_target'],
|
'conf_target': self.coin_clients[coin_to]['conf_target'],
|
||||||
@ -2311,6 +2335,7 @@ class BasicSwap(BaseApp):
|
|||||||
|
|
||||||
def createRedeemTxn(self, coin_type, bid, for_txn_type='participate', addr_redeem_out=None, fee_rate=None):
|
def createRedeemTxn(self, coin_type, bid, for_txn_type='participate', addr_redeem_out=None, fee_rate=None):
|
||||||
self.log.debug('createRedeemTxn for coin %s', str(coin_type))
|
self.log.debug('createRedeemTxn for coin %s', str(coin_type))
|
||||||
|
ci = self.ci(coin_type)
|
||||||
|
|
||||||
if for_txn_type == 'participate':
|
if for_txn_type == 'participate':
|
||||||
prev_txnid = bid.participate_tx.txid.hex()
|
prev_txnid = bid.participate_tx.txid.hex()
|
||||||
@ -2334,7 +2359,7 @@ class BasicSwap(BaseApp):
|
|||||||
'vout': prev_n,
|
'vout': prev_n,
|
||||||
'scriptPubKey': script_pub_key,
|
'scriptPubKey': script_pub_key,
|
||||||
'redeemScript': txn_script.hex(),
|
'redeemScript': txn_script.hex(),
|
||||||
'amount': format8(prev_amount)}
|
'amount': ci.format_amount(prev_amount)}
|
||||||
|
|
||||||
bid_date = dt.datetime.fromtimestamp(bid.created_at).date()
|
bid_date = dt.datetime.fromtimestamp(bid.created_at).date()
|
||||||
wif_prefix = chainparams[Coins.PART][self.chain]['key_prefix']
|
wif_prefix = chainparams[Coins.PART][self.chain]['key_prefix']
|
||||||
@ -2357,7 +2382,6 @@ class BasicSwap(BaseApp):
|
|||||||
tx_vsize = self.getContractSpendTxVSize(coin_type)
|
tx_vsize = self.getContractSpendTxVSize(coin_type)
|
||||||
tx_fee = (fee_rate * tx_vsize) / 1000
|
tx_fee = (fee_rate * tx_vsize) / 1000
|
||||||
|
|
||||||
ci = self.ci(coin_type)
|
|
||||||
self.log.debug('Redeem tx fee %s, rate %s', ci.format_amount(tx_fee, conv_int=True, r=1), str(fee_rate))
|
self.log.debug('Redeem tx fee %s, rate %s', ci.format_amount(tx_fee, conv_int=True, r=1), str(fee_rate))
|
||||||
|
|
||||||
amount_out = prev_amount - ci.make_int(tx_fee, r=1)
|
amount_out = prev_amount - ci.make_int(tx_fee, r=1)
|
||||||
@ -2373,7 +2397,7 @@ class BasicSwap(BaseApp):
|
|||||||
else:
|
else:
|
||||||
addr_redeem_out = replaceAddrPrefix(addr_redeem_out, Coins.PART, self.chain)
|
addr_redeem_out = replaceAddrPrefix(addr_redeem_out, Coins.PART, self.chain)
|
||||||
self.log.debug('addr_redeem_out %s', addr_redeem_out)
|
self.log.debug('addr_redeem_out %s', addr_redeem_out)
|
||||||
output_to = ' outaddr={}:{}'.format(format8(amount_out), addr_redeem_out)
|
output_to = ' outaddr={}:{}'.format(ci.format_amount(amount_out), addr_redeem_out)
|
||||||
if coin_type == Coins.PART:
|
if coin_type == Coins.PART:
|
||||||
redeem_txn = self.calltx('-create' + prevout_s + output_to)
|
redeem_txn = self.calltx('-create' + prevout_s + output_to)
|
||||||
else:
|
else:
|
||||||
@ -2471,7 +2495,7 @@ class BasicSwap(BaseApp):
|
|||||||
addr_refund_out = replaceAddrPrefix(addr_refund_out, Coins.PART, self.chain)
|
addr_refund_out = replaceAddrPrefix(addr_refund_out, Coins.PART, self.chain)
|
||||||
self.log.debug('addr_refund_out %s', addr_refund_out)
|
self.log.debug('addr_refund_out %s', addr_refund_out)
|
||||||
|
|
||||||
output_to = ' outaddr={}:{}'.format(format8(amount_out), addr_refund_out)
|
output_to = ' outaddr={}:{}'.format(ci.format_amount(amount_out), addr_refund_out)
|
||||||
if coin_type == Coins.PART:
|
if coin_type == Coins.PART:
|
||||||
refund_txn = self.calltx('-create' + prevout_s + output_to)
|
refund_txn = self.calltx('-create' + prevout_s + output_to)
|
||||||
else:
|
else:
|
||||||
@ -2700,8 +2724,8 @@ class BasicSwap(BaseApp):
|
|||||||
refund_tx = bid.txns[TxTypes.XMR_SWAP_A_LOCK_REFUND]
|
refund_tx = bid.txns[TxTypes.XMR_SWAP_A_LOCK_REFUND]
|
||||||
if bid.was_received:
|
if bid.was_received:
|
||||||
if bid.debug_ind == DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND:
|
if bid.debug_ind == DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND:
|
||||||
self.log.debug('XMR bid %s: Abandoning bid for testing: %d.', bid_id.hex(), bid.debug_ind)
|
self.log.debug('XMR bid %s: Stalling bid for testing: %d.', bid_id.hex(), bid.debug_ind)
|
||||||
bid.setState(BidStates.BID_ABANDONED)
|
bid.setState(BidStates.BID_STALLED_FOR_TEST)
|
||||||
rv = True
|
rv = True
|
||||||
self.saveBidInSession(bid_id, bid, session, xmr_swap)
|
self.saveBidInSession(bid_id, bid, session, xmr_swap)
|
||||||
self.logBidEvent(bid, EventLogTypes.DEBUG_TWEAK_APPLIED, 'ind {}'.format(bid.debug_ind), session)
|
self.logBidEvent(bid, EventLogTypes.DEBUG_TWEAK_APPLIED, 'ind {}'.format(bid.debug_ind), session)
|
||||||
@ -2799,7 +2823,6 @@ class BasicSwap(BaseApp):
|
|||||||
bid_changed = False
|
bid_changed = False
|
||||||
a_lock_tx_dest = ci_from.getScriptDest(xmr_swap.a_lock_tx_script)
|
a_lock_tx_dest = ci_from.getScriptDest(xmr_swap.a_lock_tx_script)
|
||||||
utxos, chain_height = ci_from.getOutput(bid.xmr_a_lock_tx.txid, a_lock_tx_dest, bid.amount)
|
utxos, chain_height = ci_from.getOutput(bid.xmr_a_lock_tx.txid, a_lock_tx_dest, bid.amount)
|
||||||
self.coin_clients[ci_from.coin_type()]['last_height'] = chain_height
|
|
||||||
|
|
||||||
if len(utxos) < 1:
|
if len(utxos) < 1:
|
||||||
return rv
|
return rv
|
||||||
@ -2869,7 +2892,6 @@ class BasicSwap(BaseApp):
|
|||||||
|
|
||||||
if bid.xmr_b_lock_tx and bid.xmr_b_lock_tx.chain_height is not None and bid.xmr_b_lock_tx.chain_height > 0:
|
if bid.xmr_b_lock_tx and bid.xmr_b_lock_tx.chain_height is not None and bid.xmr_b_lock_tx.chain_height > 0:
|
||||||
chain_height = ci_to.getChainHeight()
|
chain_height = ci_to.getChainHeight()
|
||||||
self.coin_clients[ci_to.coin_type()]['last_height'] = chain_height
|
|
||||||
|
|
||||||
if chain_height - bid.xmr_b_lock_tx.chain_height >= ci_to.blocks_confirmed:
|
if chain_height - bid.xmr_b_lock_tx.chain_height >= ci_to.blocks_confirmed:
|
||||||
self.logBidEvent(bid, EventLogTypes.LOCK_TX_B_CONFIRMED, '', session)
|
self.logBidEvent(bid, EventLogTypes.LOCK_TX_B_CONFIRMED, '', session)
|
||||||
@ -3476,7 +3498,9 @@ class BasicSwap(BaseApp):
|
|||||||
# Validate data
|
# Validate data
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
coin_from = Coins(offer_data.coin_from)
|
coin_from = Coins(offer_data.coin_from)
|
||||||
|
ci_from = self.ci(coin_from)
|
||||||
coin_to = Coins(offer_data.coin_to)
|
coin_to = Coins(offer_data.coin_to)
|
||||||
|
ci_to = self.ci(coin_to)
|
||||||
chain_from = chainparams[coin_from][self.chain]
|
chain_from = chainparams[coin_from][self.chain]
|
||||||
assert(offer_data.coin_from != offer_data.coin_to), 'coin_from == coin_to'
|
assert(offer_data.coin_from != offer_data.coin_to), 'coin_from == coin_to'
|
||||||
|
|
||||||
@ -3536,8 +3560,8 @@ class BasicSwap(BaseApp):
|
|||||||
xmr_offer = XmrOffer()
|
xmr_offer = XmrOffer()
|
||||||
|
|
||||||
xmr_offer.offer_id = offer_id
|
xmr_offer.offer_id = offer_id
|
||||||
xmr_offer.lock_time_1 = getExpectedSequence(offer_data.lock_type, offer_data.lock_value, coin_from)
|
xmr_offer.lock_time_1 = ci_from.getExpectedSequence(offer_data.lock_type, offer_data.lock_value)
|
||||||
xmr_offer.lock_time_2 = getExpectedSequence(offer_data.lock_type, offer_data.lock_value, coin_from)
|
xmr_offer.lock_time_2 = ci_from.getExpectedSequence(offer_data.lock_type, offer_data.lock_value)
|
||||||
|
|
||||||
xmr_offer.a_fee_rate = offer_data.fee_rate_from
|
xmr_offer.a_fee_rate = offer_data.fee_rate_from
|
||||||
xmr_offer.b_fee_rate = offer_data.fee_rate_to
|
xmr_offer.b_fee_rate = offer_data.fee_rate_to
|
||||||
@ -3705,6 +3729,7 @@ class BasicSwap(BaseApp):
|
|||||||
assert(bid is not None and bid.was_sent is True), 'Unknown bidid'
|
assert(bid is not None and bid.was_sent is True), 'Unknown bidid'
|
||||||
assert(offer), 'Offer not found ' + bid.offer_id.hex()
|
assert(offer), 'Offer not found ' + bid.offer_id.hex()
|
||||||
coin_from = Coins(offer.coin_from)
|
coin_from = Coins(offer.coin_from)
|
||||||
|
ci_from = self.ci(coin_from)
|
||||||
|
|
||||||
assert(bid.expire_at > now + self._bid_expired_leeway), 'Bid expired'
|
assert(bid.expire_at > now + self._bid_expired_leeway), 'Bid expired'
|
||||||
|
|
||||||
@ -3730,7 +3755,7 @@ class BasicSwap(BaseApp):
|
|||||||
|
|
||||||
script_lock_value = int(scriptvalues[2])
|
script_lock_value = int(scriptvalues[2])
|
||||||
if use_csv:
|
if use_csv:
|
||||||
expect_sequence = getExpectedSequence(offer.lock_type, offer.lock_value, coin_from)
|
expect_sequence = ci_from.getExpectedSequence(offer.lock_type, offer.lock_value)
|
||||||
assert(script_lock_value == expect_sequence), 'sequence mismatch'
|
assert(script_lock_value == expect_sequence), 'sequence mismatch'
|
||||||
else:
|
else:
|
||||||
if offer.lock_type == ABS_LOCK_BLOCKS:
|
if offer.lock_type == ABS_LOCK_BLOCKS:
|
||||||
@ -3803,7 +3828,7 @@ class BasicSwap(BaseApp):
|
|||||||
if self.countAcceptedBids(bid.offer_id) > 0:
|
if self.countAcceptedBids(bid.offer_id) > 0:
|
||||||
self.log.info('Not auto accepting bid %s, already have', bid.bid_id.hex())
|
self.log.info('Not auto accepting bid %s, already have', bid.bid_id.hex())
|
||||||
elif bid.amount != offer.amount_from:
|
elif bid.amount != offer.amount_from:
|
||||||
self.log.info('Not auto accepting bid %s, want exact amount match', bid_id.hex())
|
self.log.info('Not auto accepting bid %s, want exact amount match', bid.bid_id.hex())
|
||||||
else:
|
else:
|
||||||
delay = random.randrange(self.min_delay_event, self.max_delay_event)
|
delay = random.randrange(self.min_delay_event, self.max_delay_event)
|
||||||
self.log.info('Auto accepting xmr bid %s in %d seconds', bid.bid_id.hex(), delay)
|
self.log.info('Auto accepting xmr bid %s in %d seconds', bid.bid_id.hex(), delay)
|
||||||
@ -4155,8 +4180,8 @@ class BasicSwap(BaseApp):
|
|||||||
ci_to = self.ci(coin_to)
|
ci_to = self.ci(coin_to)
|
||||||
|
|
||||||
if bid.debug_ind == DebugTypes.BID_STOP_AFTER_COIN_A_LOCK:
|
if bid.debug_ind == DebugTypes.BID_STOP_AFTER_COIN_A_LOCK:
|
||||||
self.log.debug('XMR bid %s: Abandoning bid for testing: %d.', bid_id.hex(), bid.debug_ind)
|
self.log.debug('XMR bid %s: Stalling bid for testing: %d.', bid_id.hex(), bid.debug_ind)
|
||||||
bid.setState(BidStates.BID_ABANDONED)
|
bid.setState(BidStates.BID_STALLED_FOR_TEST)
|
||||||
self.saveBidInSession(bid_id, bid, session, xmr_swap, save_in_progress=offer)
|
self.saveBidInSession(bid_id, bid, session, xmr_swap, save_in_progress=offer)
|
||||||
self.logBidEvent(bid, EventLogTypes.DEBUG_TWEAK_APPLIED, 'ind {}'.format(bid.debug_ind), session)
|
self.logBidEvent(bid, EventLogTypes.DEBUG_TWEAK_APPLIED, 'ind {}'.format(bid.debug_ind), session)
|
||||||
return
|
return
|
||||||
@ -4890,7 +4915,8 @@ class BasicSwap(BaseApp):
|
|||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
session = scoped_session(self.session_factory)
|
session = scoped_session(self.session_factory)
|
||||||
|
|
||||||
query_str = 'SELECT bids.created_at, bids.bid_id, bids.offer_id, bids.amount, bids.state, bids.was_received, tx1.state, tx2.state FROM bids ' + \
|
query_str = 'SELECT bids.created_at, bids.bid_id, bids.offer_id, bids.amount, bids.state, bids.was_received, tx1.state, tx2.state, offers.coin_from FROM bids ' + \
|
||||||
|
'LEFT JOIN offers ON offers.offer_id = bids.offer_id ' + \
|
||||||
'LEFT JOIN transactions AS tx1 ON tx1.bid_id = bids.bid_id AND tx1.tx_type = {} '.format(TxTypes.ITX) + \
|
'LEFT JOIN transactions AS tx1 ON tx1.bid_id = bids.bid_id AND tx1.tx_type = {} '.format(TxTypes.ITX) + \
|
||||||
'LEFT JOIN transactions AS tx2 ON tx2.bid_id = bids.bid_id AND tx2.tx_type = {} '.format(TxTypes.PTX)
|
'LEFT JOIN transactions AS tx2 ON tx2.bid_id = bids.bid_id AND tx2.tx_type = {} '.format(TxTypes.PTX)
|
||||||
|
|
||||||
|
@ -10,28 +10,29 @@ CONFIG_FILENAME = 'basicswap.json'
|
|||||||
DEFAULT_DATADIR = '~/.basicswap'
|
DEFAULT_DATADIR = '~/.basicswap'
|
||||||
DEFAULT_ALLOW_CORS = False
|
DEFAULT_ALLOW_CORS = False
|
||||||
TEST_DATADIRS = os.path.expanduser(os.getenv('DATADIRS', '/tmp/basicswap'))
|
TEST_DATADIRS = os.path.expanduser(os.getenv('DATADIRS', '/tmp/basicswap'))
|
||||||
|
DEFAULT_TEST_BINDIR = os.path.expanduser(os.getenv('DEFAULT_TEST_BINDIR', '~/tmp/bin'))
|
||||||
|
|
||||||
bin_suffix = ('.exe' if os.name == 'nt' else '')
|
bin_suffix = ('.exe' if os.name == 'nt' else '')
|
||||||
PARTICL_BINDIR = os.path.expanduser(os.getenv('PARTICL_BINDIR', ''))
|
PARTICL_BINDIR = os.path.expanduser(os.getenv('PARTICL_BINDIR', os.path.join(DEFAULT_TEST_BINDIR, 'particl')))
|
||||||
PARTICLD = os.getenv('PARTICLD', 'particld' + bin_suffix)
|
PARTICLD = os.getenv('PARTICLD', 'particld' + bin_suffix)
|
||||||
PARTICL_CLI = os.getenv('PARTICL_CLI', 'particl-cli' + bin_suffix)
|
PARTICL_CLI = os.getenv('PARTICL_CLI', 'particl-cli' + bin_suffix)
|
||||||
PARTICL_TX = os.getenv('PARTICL_TX', 'particl-tx' + bin_suffix)
|
PARTICL_TX = os.getenv('PARTICL_TX', 'particl-tx' + bin_suffix)
|
||||||
|
|
||||||
BITCOIN_BINDIR = os.path.expanduser(os.getenv('BITCOIN_BINDIR', ''))
|
BITCOIN_BINDIR = os.path.expanduser(os.getenv('BITCOIN_BINDIR', os.path.join(DEFAULT_TEST_BINDIR, 'bitcoin')))
|
||||||
BITCOIND = os.getenv('BITCOIND', 'bitcoind' + bin_suffix)
|
BITCOIND = os.getenv('BITCOIND', 'bitcoind' + bin_suffix)
|
||||||
BITCOIN_CLI = os.getenv('BITCOIN_CLI', 'bitcoin-cli' + bin_suffix)
|
BITCOIN_CLI = os.getenv('BITCOIN_CLI', 'bitcoin-cli' + bin_suffix)
|
||||||
BITCOIN_TX = os.getenv('BITCOIN_TX', 'bitcoin-tx' + bin_suffix)
|
BITCOIN_TX = os.getenv('BITCOIN_TX', 'bitcoin-tx' + bin_suffix)
|
||||||
|
|
||||||
LITECOIN_BINDIR = os.path.expanduser(os.getenv('LITECOIN_BINDIR', ''))
|
LITECOIN_BINDIR = os.path.expanduser(os.getenv('LITECOIN_BINDIR', os.path.join(DEFAULT_TEST_BINDIR, 'litecoin')))
|
||||||
LITECOIND = os.getenv('LITECOIND', 'litecoind' + bin_suffix)
|
LITECOIND = os.getenv('LITECOIND', 'litecoind' + bin_suffix)
|
||||||
LITECOIN_CLI = os.getenv('LITECOIN_CLI', 'litecoin-cli' + bin_suffix)
|
LITECOIN_CLI = os.getenv('LITECOIN_CLI', 'litecoin-cli' + bin_suffix)
|
||||||
LITECOIN_TX = os.getenv('LITECOIN_TX', 'litecoin-tx' + bin_suffix)
|
LITECOIN_TX = os.getenv('LITECOIN_TX', 'litecoin-tx' + bin_suffix)
|
||||||
|
|
||||||
NAMECOIN_BINDIR = os.path.expanduser(os.getenv('NAMECOIN_BINDIR', ''))
|
NAMECOIN_BINDIR = os.path.expanduser(os.getenv('NAMECOIN_BINDIR', os.path.join(DEFAULT_TEST_BINDIR, 'namecoin')))
|
||||||
NAMECOIND = os.getenv('NAMECOIND', 'namecoind' + bin_suffix)
|
NAMECOIND = os.getenv('NAMECOIND', 'namecoind' + bin_suffix)
|
||||||
NAMECOIN_CLI = os.getenv('NAMECOIN_CLI', 'namecoin-cli' + bin_suffix)
|
NAMECOIN_CLI = os.getenv('NAMECOIN_CLI', 'namecoin-cli' + bin_suffix)
|
||||||
NAMECOIN_TX = os.getenv('NAMECOIN_TX', 'namecoin-tx' + bin_suffix)
|
NAMECOIN_TX = os.getenv('NAMECOIN_TX', 'namecoin-tx' + bin_suffix)
|
||||||
|
|
||||||
XMR_BINDIR = os.path.expanduser(os.getenv('XMR_BINDIR', ''))
|
XMR_BINDIR = os.path.expanduser(os.getenv('XMR_BINDIR', os.path.join(DEFAULT_TEST_BINDIR, 'monero')))
|
||||||
XMRD = os.getenv('XMRD', 'monerod' + bin_suffix)
|
XMRD = os.getenv('XMRD', 'monerod' + bin_suffix)
|
||||||
XMR_WALLET_RPC = os.getenv('XMR_WALLET_RPC', 'monero-wallet-rpc' + bin_suffix)
|
XMR_WALLET_RPC = os.getenv('XMR_WALLET_RPC', 'monero-wallet-rpc' + bin_suffix)
|
||||||
|
@ -62,10 +62,19 @@ from .contrib.test_framework.script import (
|
|||||||
SegwitV0SignatureHash,
|
SegwitV0SignatureHash,
|
||||||
hash160)
|
hash160)
|
||||||
|
|
||||||
|
from .types import (
|
||||||
|
SEQUENCE_LOCK_BLOCKS,
|
||||||
|
SEQUENCE_LOCK_TIME)
|
||||||
|
|
||||||
from .chainparams import CoinInterface, Coins, chainparams
|
from .chainparams import CoinInterface, Coins, chainparams
|
||||||
from .rpc import make_rpc_func
|
from .rpc import make_rpc_func
|
||||||
|
|
||||||
|
|
||||||
|
SEQUENCE_LOCKTIME_GRANULARITY = 9 # 512 seconds
|
||||||
|
SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22)
|
||||||
|
SEQUENCE_LOCKTIME_MASK = 0x0000ffff
|
||||||
|
|
||||||
|
|
||||||
def findOutput(tx, script_pk):
|
def findOutput(tx, script_pk):
|
||||||
for i in range(len(tx.vout)):
|
for i in range(len(tx.vout)):
|
||||||
if tx.vout[i].scriptPubKey == script_pk:
|
if tx.vout[i].scriptPubKey == script_pk:
|
||||||
@ -121,6 +130,27 @@ class BTCInterface(CoinInterface):
|
|||||||
def txoType():
|
def txoType():
|
||||||
return CTxOut
|
return CTxOut
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getExpectedSequence(lockType, lockVal):
|
||||||
|
assert(lockVal >= 1), 'Bad lockVal'
|
||||||
|
if lockType == SEQUENCE_LOCK_BLOCKS:
|
||||||
|
return lockVal
|
||||||
|
if lockType == SEQUENCE_LOCK_TIME:
|
||||||
|
secondsLocked = lockVal
|
||||||
|
# Ensure the locked time is never less than lockVal
|
||||||
|
if secondsLocked % (1 << SEQUENCE_LOCKTIME_GRANULARITY) != 0:
|
||||||
|
secondsLocked += (1 << SEQUENCE_LOCKTIME_GRANULARITY)
|
||||||
|
secondsLocked >>= SEQUENCE_LOCKTIME_GRANULARITY
|
||||||
|
return secondsLocked | SEQUENCE_LOCKTIME_TYPE_FLAG
|
||||||
|
raise ValueError('Unknown lock type')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def decodeSequence(lock_value):
|
||||||
|
# Return the raw value
|
||||||
|
if lock_value & SEQUENCE_LOCKTIME_TYPE_FLAG:
|
||||||
|
return (lock_value & SEQUENCE_LOCKTIME_MASK) << SEQUENCE_LOCKTIME_GRANULARITY
|
||||||
|
return lock_value & SEQUENCE_LOCKTIME_MASK
|
||||||
|
|
||||||
def __init__(self, coin_settings, network, swap_client=None):
|
def __init__(self, coin_settings, network, swap_client=None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
rpc_host = coin_settings.get('rpchost', '127.0.0.1')
|
rpc_host = coin_settings.get('rpchost', '127.0.0.1')
|
||||||
@ -129,7 +159,7 @@ class BTCInterface(CoinInterface):
|
|||||||
self.blocks_confirmed = coin_settings['blocks_confirmed']
|
self.blocks_confirmed = coin_settings['blocks_confirmed']
|
||||||
self.setConfTarget(coin_settings['conf_target'])
|
self.setConfTarget(coin_settings['conf_target'])
|
||||||
self._sc = swap_client
|
self._sc = swap_client
|
||||||
self._log = self._sc.log if self._sc.log else logging
|
self._log = self._sc.log if self._sc and self._sc.log else logging
|
||||||
|
|
||||||
def setConfTarget(self, new_conf_target):
|
def setConfTarget(self, new_conf_target):
|
||||||
assert(new_conf_target >= 1 and new_conf_target < 33), 'Invalid conf_target value'
|
assert(new_conf_target >= 1 and new_conf_target < 33), 'Invalid conf_target value'
|
||||||
@ -154,6 +184,9 @@ class BTCInterface(CoinInterface):
|
|||||||
block_hash = self.rpc_callback('getblockhash', [height])
|
block_hash = self.rpc_callback('getblockhash', [height])
|
||||||
return self.rpc_callback('getblockheader', [block_hash])
|
return self.rpc_callback('getblockheader', [block_hash])
|
||||||
|
|
||||||
|
def getBlockHeader(self, block_hash):
|
||||||
|
return self.rpc_callback('getblockheader', [block_hash])
|
||||||
|
|
||||||
def initialiseWallet(self, key_bytes):
|
def initialiseWallet(self, key_bytes):
|
||||||
wif_prefix = chainparams[self.coin_type()][self._network]['key_prefix']
|
wif_prefix = chainparams[self.coin_type()][self._network]['key_prefix']
|
||||||
key_wif = toWIF(wif_prefix, key_bytes)
|
key_wif = toWIF(wif_prefix, key_bytes)
|
||||||
@ -363,7 +396,7 @@ class BTCInterface(CoinInterface):
|
|||||||
tx.vout.append(self.txoType()(locked_coin, self.getScriptForPubkeyHash(pkh_refund_to)))
|
tx.vout.append(self.txoType()(locked_coin, self.getScriptForPubkeyHash(pkh_refund_to)))
|
||||||
|
|
||||||
witness_bytes = len(script_lock_refund)
|
witness_bytes = len(script_lock_refund)
|
||||||
witness_bytes += 73 * 2 # 2 signatures (72 + 1 byte size)
|
witness_bytes += 74 * 2 # 2 signatures (72 + 1 byte sighashtype + 1 byte size) - Use maximum txn size for estimate
|
||||||
witness_bytes += 4 # 1 empty, 1 true witness stack values
|
witness_bytes += 4 # 1 empty, 1 true witness stack values
|
||||||
witness_bytes += getCompactSizeLen(witness_bytes)
|
witness_bytes += getCompactSizeLen(witness_bytes)
|
||||||
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
|
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
|
||||||
@ -398,7 +431,7 @@ class BTCInterface(CoinInterface):
|
|||||||
tx.vout.append(self.txoType()(locked_coin, self.getScriptForPubkeyHash(pkh_dest)))
|
tx.vout.append(self.txoType()(locked_coin, self.getScriptForPubkeyHash(pkh_dest)))
|
||||||
|
|
||||||
witness_bytes = len(script_lock_refund)
|
witness_bytes = len(script_lock_refund)
|
||||||
witness_bytes += 73 # signature (72 + 1 byte size)
|
witness_bytes += 74 # 2 signatures (72 + 1 byte sighashtype + 1 byte size) - Use maximum txn size for estimate
|
||||||
witness_bytes += 1 # 1 empty stack value
|
witness_bytes += 1 # 1 empty stack value
|
||||||
witness_bytes += getCompactSizeLen(witness_bytes)
|
witness_bytes += getCompactSizeLen(witness_bytes)
|
||||||
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
|
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
|
||||||
@ -429,7 +462,7 @@ class BTCInterface(CoinInterface):
|
|||||||
|
|
||||||
witness_bytes = len(script_lock)
|
witness_bytes = len(script_lock)
|
||||||
witness_bytes += 33 # sv, size
|
witness_bytes += 33 # sv, size
|
||||||
witness_bytes += 73 * 2 # 2 signatures (72 + 1 byte size)
|
witness_bytes += 74 * 2 # 2 signatures (72 + 1 byte sighashtype + 1 byte size) - Use maximum txn size for estimate
|
||||||
witness_bytes += 4 # 1 empty, 1 true witness stack values
|
witness_bytes += 4 # 1 empty, 1 true witness stack values
|
||||||
witness_bytes += getCompactSizeLen(witness_bytes)
|
witness_bytes += getCompactSizeLen(witness_bytes)
|
||||||
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
|
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
|
||||||
@ -546,7 +579,7 @@ class BTCInterface(CoinInterface):
|
|||||||
assert(fee_paid > 0)
|
assert(fee_paid > 0)
|
||||||
|
|
||||||
witness_bytes = len(prevout_script)
|
witness_bytes = len(prevout_script)
|
||||||
witness_bytes += 73 * 2 # 2 signatures (72 + 1 byts size)
|
witness_bytes += 74 * 2 # 2 signatures (72 + 1 byte sighashtype + 1 byte size) - Use maximum txn size for estimate
|
||||||
witness_bytes += 2 # 2 empty witness stack values
|
witness_bytes += 2 # 2 empty witness stack values
|
||||||
witness_bytes += getCompactSizeLen(witness_bytes)
|
witness_bytes += getCompactSizeLen(witness_bytes)
|
||||||
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
|
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
|
||||||
@ -555,7 +588,7 @@ class BTCInterface(CoinInterface):
|
|||||||
self._log.info('tx amount, vsize, feerate: %ld, %ld, %ld', locked_coin, vsize, fee_rate_paid)
|
self._log.info('tx amount, vsize, feerate: %ld, %ld, %ld', locked_coin, vsize, fee_rate_paid)
|
||||||
|
|
||||||
if not self.compareFeeRates(fee_rate_paid, feerate):
|
if not self.compareFeeRates(fee_rate_paid, feerate):
|
||||||
raise ValueError('Bad fee rate')
|
raise ValueError('Bad fee rate, expected: {}'.format(feerate))
|
||||||
|
|
||||||
return tx_hash, locked_coin
|
return tx_hash, locked_coin
|
||||||
|
|
||||||
@ -592,7 +625,7 @@ class BTCInterface(CoinInterface):
|
|||||||
assert(fee_paid > 0)
|
assert(fee_paid > 0)
|
||||||
|
|
||||||
witness_bytes = len(prevout_script)
|
witness_bytes = len(prevout_script)
|
||||||
witness_bytes += 73 * 2 # 2 signatures (72 + 1 byts size)
|
witness_bytes += 74 * 2 # 2 signatures (72 + 1 byte sighashtype + 1 byte size) - Use maximum txn size for estimate
|
||||||
witness_bytes += 4 # 1 empty, 1 true witness stack values
|
witness_bytes += 4 # 1 empty, 1 true witness stack values
|
||||||
witness_bytes += getCompactSizeLen(witness_bytes)
|
witness_bytes += getCompactSizeLen(witness_bytes)
|
||||||
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
|
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
|
||||||
@ -601,7 +634,7 @@ class BTCInterface(CoinInterface):
|
|||||||
self._log.info('tx amount, vsize, feerate: %ld, %ld, %ld', tx_value, vsize, fee_rate_paid)
|
self._log.info('tx amount, vsize, feerate: %ld, %ld, %ld', tx_value, vsize, fee_rate_paid)
|
||||||
|
|
||||||
if not self.compareFeeRates(fee_rate_paid, feerate):
|
if not self.compareFeeRates(fee_rate_paid, feerate):
|
||||||
raise ValueError('Bad fee rate')
|
raise ValueError('Bad fee rate, expected: {}'.format(feerate))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -641,7 +674,7 @@ class BTCInterface(CoinInterface):
|
|||||||
|
|
||||||
witness_bytes = len(lock_tx_script)
|
witness_bytes = len(lock_tx_script)
|
||||||
witness_bytes += 33 # sv, size
|
witness_bytes += 33 # sv, size
|
||||||
witness_bytes += 73 * 2 # 2 signatures (72 + 1 byts size)
|
witness_bytes += 74 * 2 # 2 signatures (72 + 1 byte sighashtype + 1 byte size) - Use maximum txn size for estimate
|
||||||
witness_bytes += 4 # 1 empty, 1 true witness stack values
|
witness_bytes += 4 # 1 empty, 1 true witness stack values
|
||||||
witness_bytes += getCompactSizeLen(witness_bytes)
|
witness_bytes += getCompactSizeLen(witness_bytes)
|
||||||
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
|
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
|
||||||
@ -650,7 +683,7 @@ class BTCInterface(CoinInterface):
|
|||||||
self._log.info('tx amount, vsize, feerate: %ld, %ld, %ld', tx.vout[0].nValue, vsize, fee_rate_paid)
|
self._log.info('tx amount, vsize, feerate: %ld, %ld, %ld', tx.vout[0].nValue, vsize, fee_rate_paid)
|
||||||
|
|
||||||
if not self.compareFeeRates(fee_rate_paid, feerate):
|
if not self.compareFeeRates(fee_rate_paid, feerate):
|
||||||
raise ValueError('Bad fee rate')
|
raise ValueError('Bad fee rate, expected: {}'.format(feerate))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ class XMRInterface(CoinInterface):
|
|||||||
self._restore_height = coin_settings.get('restore_height', 0)
|
self._restore_height = coin_settings.get('restore_height', 0)
|
||||||
self.setFeePriority(coin_settings.get('fee_priority', 0))
|
self.setFeePriority(coin_settings.get('fee_priority', 0))
|
||||||
self._sc = swap_client
|
self._sc = swap_client
|
||||||
self._log = self._sc.log if self._sc.log else logging
|
self._log = self._sc.log if self._sc and self._sc.log else logging
|
||||||
|
|
||||||
def setFeePriority(self, new_priority):
|
def setFeePriority(self, new_priority):
|
||||||
assert(new_priority >= 0 and new_priority < 4), 'Invalid fee_priority value'
|
assert(new_priority >= 0 and new_priority < 4), 'Invalid fee_priority value'
|
||||||
|
@ -8,7 +8,6 @@ import json
|
|||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
from .util import (
|
from .util import (
|
||||||
format8,
|
|
||||||
format_timestamp,
|
format_timestamp,
|
||||||
)
|
)
|
||||||
from .basicswap import (
|
from .basicswap import (
|
||||||
@ -174,7 +173,8 @@ def js_bids(self, url_split, post_string, is_json):
|
|||||||
'bid_id': b[1].hex(),
|
'bid_id': b[1].hex(),
|
||||||
'offer_id': b[2].hex(),
|
'offer_id': b[2].hex(),
|
||||||
'created_at': format_timestamp(b[0]),
|
'created_at': format_timestamp(b[0]),
|
||||||
'amount_from': format8(b[3]),
|
'coin_from': b[8],
|
||||||
|
'amount_from': swap_client.ci(b[8]).format_amount(b[3]),
|
||||||
'bid_state': strBidState(b[4])
|
'bid_state': strBidState(b[4])
|
||||||
} for b in bids]), 'UTF-8')
|
} for b in bids]), 'UTF-8')
|
||||||
|
|
||||||
|
@ -23,6 +23,11 @@
|
|||||||
<tr><td>Expired At</td><td>{{ data.expired_at }}</td></tr>
|
<tr><td>Expired At</td><td>{{ data.expired_at }}</td></tr>
|
||||||
<tr><td>Sent</td><td>{{ data.was_sent }}</td></tr>
|
<tr><td>Sent</td><td>{{ data.was_sent }}</td></tr>
|
||||||
<tr><td>Received</td><td>{{ data.was_received }}</td></tr>
|
<tr><td>Received</td><td>{{ data.was_received }}</td></tr>
|
||||||
|
{% if data.coin_a_lock_refund_tx_est_final != 'None' %}
|
||||||
|
<tr><td>{{ data.ticker_from }} lock refund tx valid at</td><td>{{ data.coin_a_lock_refund_tx_est_final | formatts }}</td></tr>
|
||||||
|
<tr><td>{{ data.ticker_from }} chain median time</td><td>{{ data.coin_a_last_median_time | formatts }}</td></tr>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<form method="post">
|
<form method="post">
|
||||||
|
10
basicswap/types.py
Normal file
10
basicswap/types.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2021 tecnovert
|
||||||
|
# Distributed under the MIT software license, see the accompanying
|
||||||
|
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
SEQUENCE_LOCK_BLOCKS = 1
|
||||||
|
SEQUENCE_LOCK_TIME = 2
|
||||||
|
ABS_LOCK_BLOCKS = 3
|
||||||
|
ABS_LOCK_TIME = 4
|
@ -20,6 +20,9 @@ from .basicswap import (
|
|||||||
strBidState,
|
strBidState,
|
||||||
strTxState,
|
strTxState,
|
||||||
)
|
)
|
||||||
|
from .types import (
|
||||||
|
SEQUENCE_LOCK_TIME,
|
||||||
|
)
|
||||||
|
|
||||||
PAGE_LIMIT = 50
|
PAGE_LIMIT = 50
|
||||||
|
|
||||||
@ -186,15 +189,15 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
|
|||||||
txns = []
|
txns = []
|
||||||
if bid.xmr_a_lock_tx:
|
if bid.xmr_a_lock_tx:
|
||||||
confirms = None
|
confirms = None
|
||||||
if swap_client.coin_clients[ci_from.coin_type()]['last_height'] and bid.xmr_a_lock_tx.chain_height:
|
if swap_client.coin_clients[ci_from.coin_type()]['chain_height'] and bid.xmr_a_lock_tx.chain_height:
|
||||||
confirms = (swap_client.coin_clients[ci_from.coin_type()]['last_height'] - bid.xmr_a_lock_tx.chain_height) + 1
|
confirms = (swap_client.coin_clients[ci_from.coin_type()]['chain_height'] - bid.xmr_a_lock_tx.chain_height) + 1
|
||||||
txns.append({'type': 'Chain A Lock', 'txid': bid.xmr_a_lock_tx.txid.hex(), 'confirms': confirms})
|
txns.append({'type': 'Chain A Lock', 'txid': bid.xmr_a_lock_tx.txid.hex(), 'confirms': confirms})
|
||||||
if bid.xmr_a_lock_spend_tx:
|
if bid.xmr_a_lock_spend_tx:
|
||||||
txns.append({'type': 'Chain A Lock Spend', 'txid': bid.xmr_a_lock_spend_tx.txid.hex()})
|
txns.append({'type': 'Chain A Lock Spend', 'txid': bid.xmr_a_lock_spend_tx.txid.hex()})
|
||||||
if bid.xmr_b_lock_tx:
|
if bid.xmr_b_lock_tx:
|
||||||
confirms = None
|
confirms = None
|
||||||
if swap_client.coin_clients[ci_to.coin_type()]['last_height'] and bid.xmr_b_lock_tx.chain_height:
|
if swap_client.coin_clients[ci_to.coin_type()]['chain_height'] and bid.xmr_b_lock_tx.chain_height:
|
||||||
confirms = (swap_client.coin_clients[ci_to.coin_type()]['last_height'] - bid.xmr_b_lock_tx.chain_height) + 1
|
confirms = (swap_client.coin_clients[ci_to.coin_type()]['chain_height'] - bid.xmr_b_lock_tx.chain_height) + 1
|
||||||
txns.append({'type': 'Chain B Lock', 'txid': bid.xmr_b_lock_tx.txid.hex(), 'confirms': confirms})
|
txns.append({'type': 'Chain B Lock', 'txid': bid.xmr_b_lock_tx.txid.hex(), 'confirms': confirms})
|
||||||
if bid.xmr_b_lock_tx and bid.xmr_b_lock_tx.spend_txid:
|
if bid.xmr_b_lock_tx and bid.xmr_b_lock_tx.spend_txid:
|
||||||
txns.append({'type': 'Chain B Lock Spend', 'txid': bid.xmr_b_lock_tx.spend_txid.hex()})
|
txns.append({'type': 'Chain B Lock Spend', 'txid': bid.xmr_b_lock_tx.spend_txid.hex()})
|
||||||
@ -214,6 +217,15 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
|
|||||||
data['participate_tx_spend'] = getTxSpendHex(bid, TxTypes.PTX)
|
data['participate_tx_spend'] = getTxSpendHex(bid, TxTypes.PTX)
|
||||||
|
|
||||||
if offer.swap_type == SwapTypes.XMR_SWAP:
|
if offer.swap_type == SwapTypes.XMR_SWAP:
|
||||||
|
|
||||||
|
data['coin_a_lock_refund_tx_est_final'] = 'None'
|
||||||
|
if bid.xmr_a_lock_tx and bid.xmr_a_lock_tx.block_time:
|
||||||
|
if offer.lock_type == SEQUENCE_LOCK_TIME:
|
||||||
|
raw_sequence = ci_from.getExpectedSequence(offer.lock_type, offer.lock_value)
|
||||||
|
seconds_locked = ci_from.decodeSequence(raw_sequence)
|
||||||
|
data['coin_a_lock_refund_tx_est_final'] = bid.xmr_a_lock_tx.block_time + seconds_locked
|
||||||
|
data['coin_a_last_median_time'] = swap_client.coin_clients[offer.coin_from]['chain_median_time']
|
||||||
|
|
||||||
if view_tx_ind:
|
if view_tx_ind:
|
||||||
data['view_tx_ind'] = view_tx_ind
|
data['view_tx_ind'] = view_tx_ind
|
||||||
view_tx_id = bytes.fromhex(view_tx_ind)
|
view_tx_id = bytes.fromhex(view_tx_ind)
|
||||||
|
@ -27,16 +27,6 @@ def assert_cond(v, err='Bad opcode'):
|
|||||||
raise ValueError(err)
|
raise ValueError(err)
|
||||||
|
|
||||||
|
|
||||||
def format8(i):
|
|
||||||
n = abs(i)
|
|
||||||
quotient = n // COIN
|
|
||||||
remainder = n % COIN
|
|
||||||
rv = "%d.%08d" % (quotient, remainder)
|
|
||||||
if i < 0:
|
|
||||||
rv = '-' + rv
|
|
||||||
return rv
|
|
||||||
|
|
||||||
|
|
||||||
def toBool(s):
|
def toBool(s):
|
||||||
return s.lower() in ["1", "true"]
|
return s.lower() in ["1", "true"]
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ def prepareCore(coin, version, settings, data_dir):
|
|||||||
assert_url = 'https://raw.githubusercontent.com/tecnovert/gitian.sigs/master/%s-%s/%s/%s' % (version, os_dir_name, signing_key_name, assert_filename)
|
assert_url = 'https://raw.githubusercontent.com/tecnovert/gitian.sigs/master/%s-%s/%s/%s' % (version, os_dir_name, signing_key_name, assert_filename)
|
||||||
elif coin == 'litecoin':
|
elif coin == 'litecoin':
|
||||||
signing_key_name = 'thrasher'
|
signing_key_name = 'thrasher'
|
||||||
release_url = 'https://download.litecoin.org/litecoin-{}/{}/{}'.format(version, os_name, release_filename)
|
release_url = 'https://download2.litecoin.org/litecoin-{}/{}/{}'.format(version, os_name, release_filename)
|
||||||
assert_filename = '{}-{}-{}-build.assert'.format(coin, os_name, version.rsplit('.', 1)[0])
|
assert_filename = '{}-{}-{}-build.assert'.format(coin, os_name, version.rsplit('.', 1)[0])
|
||||||
assert_url = 'https://raw.githubusercontent.com/litecoin-project/gitian.sigs.ltc/master/%s-%s/%s/%s' % (version, os_dir_name, signing_key_name, assert_filename)
|
assert_url = 'https://raw.githubusercontent.com/litecoin-project/gitian.sigs.ltc/master/%s-%s/%s/%s' % (version, os_dir_name, signing_key_name, assert_filename)
|
||||||
elif coin == 'bitcoin':
|
elif coin == 'bitcoin':
|
||||||
|
@ -30,10 +30,7 @@ from basicswap.util import (
|
|||||||
make_int,
|
make_int,
|
||||||
format_amount,
|
format_amount,
|
||||||
validate_amount)
|
validate_amount)
|
||||||
from basicswap.basicswap import (
|
from basicswap.types import (
|
||||||
Coins,
|
|
||||||
getExpectedSequence,
|
|
||||||
decodeSequence,
|
|
||||||
SEQUENCE_LOCK_BLOCKS,
|
SEQUENCE_LOCK_BLOCKS,
|
||||||
SEQUENCE_LOCK_TIME)
|
SEQUENCE_LOCK_TIME)
|
||||||
|
|
||||||
@ -57,21 +54,24 @@ class Test(unittest.TestCase):
|
|||||||
test_case(4194642)
|
test_case(4194642)
|
||||||
|
|
||||||
def test_sequence(self):
|
def test_sequence(self):
|
||||||
|
coin_settings = {'rpcport': 0, 'rpcauth': 'none', 'blocks_confirmed': 1, 'conf_target': 1}
|
||||||
|
ci = BTCInterface(coin_settings, 'regtest')
|
||||||
|
|
||||||
time_val = 48 * 60 * 60
|
time_val = 48 * 60 * 60
|
||||||
encoded = getExpectedSequence(SEQUENCE_LOCK_TIME, time_val, Coins.PART)
|
encoded = ci.getExpectedSequence(SEQUENCE_LOCK_TIME, time_val)
|
||||||
decoded = decodeSequence(encoded)
|
decoded = ci.decodeSequence(encoded)
|
||||||
assert(decoded >= time_val)
|
assert(decoded >= time_val)
|
||||||
assert(decoded <= time_val + 512)
|
assert(decoded <= time_val + 512)
|
||||||
|
|
||||||
time_val = 24 * 60
|
time_val = 24 * 60
|
||||||
encoded = getExpectedSequence(SEQUENCE_LOCK_TIME, time_val, Coins.PART)
|
encoded = ci.getExpectedSequence(SEQUENCE_LOCK_TIME, time_val)
|
||||||
decoded = decodeSequence(encoded)
|
decoded = ci.decodeSequence(encoded)
|
||||||
assert(decoded >= time_val)
|
assert(decoded >= time_val)
|
||||||
assert(decoded <= time_val + 512)
|
assert(decoded <= time_val + 512)
|
||||||
|
|
||||||
blocks_val = 123
|
blocks_val = 123
|
||||||
encoded = getExpectedSequence(SEQUENCE_LOCK_BLOCKS, blocks_val, Coins.PART)
|
encoded = ci.getExpectedSequence(SEQUENCE_LOCK_BLOCKS, blocks_val)
|
||||||
decoded = decodeSequence(encoded)
|
decoded = ci.decodeSequence(encoded)
|
||||||
assert(decoded == blocks_val)
|
assert(decoded == blocks_val)
|
||||||
|
|
||||||
def test_make_int(self):
|
def test_make_int(self):
|
||||||
|
@ -554,14 +554,14 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
wait_for_bid(delay_event, swap_clients[0], bid_id)
|
wait_for_bid(delay_event, swap_clients[0], bid_id)
|
||||||
swap_clients[0].acceptBid(bid_id)
|
swap_clients[0].acceptBid(bid_id)
|
||||||
swap_clients[0].coin_clients[Coins.BTC]['override_feerate'] = 10.0
|
swap_clients[0].getChainClientSettings(Coins.BTC)['override_feerate'] = 10.0
|
||||||
swap_clients[0].coin_clients[Coins.LTC]['override_feerate'] = 10.0
|
swap_clients[0].getChainClientSettings(Coins.LTC)['override_feerate'] = 10.0
|
||||||
|
|
||||||
wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=60)
|
wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=60)
|
||||||
|
|
||||||
swap_clients[0].abandonBid(bid_id)
|
swap_clients[0].abandonBid(bid_id)
|
||||||
del swap_clients[0].coin_clients[Coins.BTC]['override_feerate']
|
del swap_clients[0].getChainClientSettings(Coins.BTC)['override_feerate']
|
||||||
del swap_clients[0].coin_clients[Coins.LTC]['override_feerate']
|
del swap_clients[0].getChainClientSettings(Coins.LTC)['override_feerate']
|
||||||
|
|
||||||
def test_08_part_ltc_buyer_first(self):
|
def test_08_part_ltc_buyer_first(self):
|
||||||
logging.info('---------- Test PART to LTC, buyer first')
|
logging.info('---------- Test PART to LTC, buyer first')
|
||||||
|
@ -515,7 +515,7 @@ class Test(unittest.TestCase):
|
|||||||
|
|
||||||
swap_clients[0].acceptXmrBid(bid_id)
|
swap_clients[0].acceptXmrBid(bid_id)
|
||||||
|
|
||||||
wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.BID_ABANDONED, wait_for=180)
|
wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.BID_STALLED_FOR_TEST, wait_for=180)
|
||||||
wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_SWIPED, wait_for=80, sent=True)
|
wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_SWIPED, wait_for=80, sent=True)
|
||||||
|
|
||||||
js_w0_after = json.loads(urlopen('http://127.0.0.1:1800/json/wallets').read())
|
js_w0_after = json.loads(urlopen('http://127.0.0.1:1800/json/wallets').read())
|
||||||
|
Loading…
Reference in New Issue
Block a user