Fix contract_count not inserted in db

2024-05-20_merge
tecnovert 4 years ago
parent 5d84d54e6f
commit acae8b4de3
No known key found for this signature in database
GPG Key ID: 8ED6D8750C4E3F93
  1. 2
      basicswap/__init__.py
  2. 82
      basicswap/basicswap.py
  3. 13
      basicswap/chainparams.py
  4. 4
      basicswap/config.py
  5. 51
      basicswap/contrib/rpcauth.py
  6. 18
      basicswap/interface_btc.py
  7. 12
      basicswap/interface_nmc.py
  8. 3
      basicswap/interface_part.py
  9. 28
      basicswap/interface_xmr.py
  10. 28
      basicswap/messages.proto
  11. 297
      basicswap/messages_pb2.py
  12. 9
      basicswap/rpc.py
  13. 32
      basicswap/util.py
  14. 10
      bin/basicswap_prepare.py
  15. 10
      bin/basicswap_run.py
  16. 1
      setup.py
  17. 7
      tests/basicswap/common.py
  18. 8
      tests/basicswap/test_nmc.py
  19. 25
      tests/basicswap/test_run.py
  20. 442
      tests/basicswap/test_xmr.py

@ -1,3 +1,3 @@
name = "basicswap"
__version__ = "0.0.4"
__version__ = "0.0.5"

@ -22,6 +22,7 @@ from enum import IntEnum, auto
from .interface_part import PARTInterface
from .interface_btc import BTCInterface
from .interface_ltc import LTCInterface
from .interface_nmc import NMCInterface
from .interface_xmr import XMRInterface
from . import __version__
@ -29,6 +30,7 @@ from .util import (
COIN,
pubkeyToAddress,
format8,
format_amount,
encodeAddress,
decodeAddress,
SerialiseNum,
@ -80,12 +82,15 @@ class MessageTypes(IntEnum):
BID = auto()
BID_ACCEPT = auto()
XMR_OFFER = auto()
class SwapTypes(IntEnum):
SELLER_FIRST = auto()
BUYER_FIRST = auto()
SELLER_FIRST_2MSG = auto()
BUYER_FIRST_2MSG = auto()
XMR_SWAP = auto()
class OfferStates(IntEnum):
@ -317,7 +322,7 @@ class BasicSwap(BaseApp):
self.network_pubkey = self.settings['network_pubkey']
self.network_addr = pubkeyToAddress(chainparams[Coins.PART][self.chain]['pubkey_address'], bytearray.fromhex(self.network_pubkey))
self.wallet = self.settings.get('wallet', None) # TODO: Move to coin_clients
#self.wallet = self.settings.get('wallet', None) # TODO: Move to coin_clients
self.sqlite_file = os.path.join(self.data_dir, 'db{}.sqlite'.format('' if self.chain == 'mainnet' else ('_' + self.chain)))
db_exists = os.path.exists(self.sqlite_file)
@ -341,6 +346,20 @@ class BasicSwap(BaseApp):
self._contract_count = session.query(DBKVInt).filter_by(key='contract_count').first().value
except Exception:
self._contract_count = 0
session.add(DBKVInt(
key='contract_count',
value=self._contract_count
))
session.commit()
try:
self._offer_count = session.query(DBKVInt).filter_by(key='offer_count').first().value
except Exception:
self._offer_count = 0
session.add(DBKVInt(
key='offer_count',
value=self._offer_count
))
session.commit()
session.close()
session.remove()
@ -426,7 +445,7 @@ class BasicSwap(BaseApp):
if coin == Coins.XMR:
self.coin_clients[coin]['walletrpcport'] = chain_client_settings.get('walletrpcport', chainparams[coin][self.chain]['walletrpcport'])
if 'walletrpcpassword' in chain_client_settings:
self.coin_clients[coin]['walletrpcauth'] = chain_client_settings['walletrpcuser'] + ':' + chain_client_settings['walletrpcpassword']
self.coin_clients[coin]['walletrpcauth'] = (chain_client_settings['walletrpcuser'], chain_client_settings['walletrpcpassword'])
else:
raise ValueError('Missing XMR wallet rpc credentials.')
self.coin_clients[coin]['interface'] = self.createInterface(coin)
@ -438,6 +457,8 @@ class BasicSwap(BaseApp):
return BTCInterface(self.coin_clients[coin])
elif coin == Coins.LTC:
return LTCInterface(self.coin_clients[coin])
elif coin == Coins.NMC:
return NMCInterface(self.coin_clients[coin])
elif coin == Coins.XMR:
return XMRInterface(self.coin_clients[coin])
else:
@ -445,6 +466,8 @@ class BasicSwap(BaseApp):
def setCoinRunParams(self, coin):
cc = self.coin_clients[coin]
if coin == Coins.XMR:
return
if cc['connection_type'] == 'rpc' and cc['rpcauth'] is None:
chain_client_settings = self.getChainClientSettings(coin)
authcookiepath = os.path.join(self.getChainDatadirPath(coin), '.cookie')
@ -474,6 +497,10 @@ class BasicSwap(BaseApp):
self.log.error('Unable to read authcookie for %s, %s, datadir pid %d, daemon pid %s', str(coin), authcookiepath, datadir_pid, cc['pid'])
raise ValueError('Error, terminating')
def createCoinInterface(self, coin):
if self.coin_clients[coin]['connection_type'] == 'rpc':
self.coin_clients[coin]['interface'] = self.createInterface(coin)
def start(self):
self.log.info('Starting BasicSwap %s\n\n', __version__)
self.log.info('sqlalchemy version %s', sa.__version__)
@ -482,9 +509,11 @@ class BasicSwap(BaseApp):
for c in Coins:
self.setCoinRunParams(c)
self.createCoinInterface(c)
if self.coin_clients[c]['connection_type'] == 'rpc':
self.waitForDaemonRPC(c)
core_version = self.callcoinrpc(c, 'getnetworkinfo')['version']
core_version = self.coin_clients[c]['interface'].getDaemonVersion()
self.log.info('%s Core version %d', chainparams[c]['name'].capitalize(), core_version)
self.coin_clients[c]['core_version'] = core_version
@ -540,7 +569,7 @@ class BasicSwap(BaseApp):
if not self.is_running:
return
try:
self.callcoinrpc(coin_type, 'getwalletinfo', [], self.wallet)
self.coin_clients[coin_type]['interface'].testDaemonRPC()
return
except Exception as ex:
self.log.warning('Can\'t connect to %s RPC: %s. Trying again in %d second/s.', coin_type, str(ex), (1 + i))
@ -707,10 +736,19 @@ class BasicSwap(BaseApp):
self.mxDB.acquire()
try:
self.checkSynced(coin_from_t, coin_to_t)
# TODO: require proof of funds on offers?
proof_addr, proof_sig = self.getProofOfFunds(coin_from_t, amount)
# TODO: require prrof of funds on offers?
offer_addr = self.callrpc('getnewaddress') if addr_send_from is None else addr_send_from
offer_created_at = int(time.time())
if swap_type == SwapTypes.XMR_SWAP:
msg_buf = XmrOfferMessage()
key_path = "44445555h/999999/{}/{}/{}/{}".format(int(coin_from), int(coin_to), offer_created_at, )
else:
msg_buf = OfferMessage()
msg_buf = OfferMessage()
msg_buf.coin_from = int(coin_from)
msg_buf.coin_to = int(coin_to)
msg_buf.amount_from = int(amount)
@ -725,10 +763,6 @@ class BasicSwap(BaseApp):
offer_bytes = msg_buf.SerializeToString()
payload_hex = str.format('{:02x}', MessageTypes.OFFER) + offer_bytes.hex()
if addr_send_from is None:
offer_addr = self.callrpc('getnewaddress')
else:
offer_addr = addr_send_from
self.callrpc('smsgaddlocaladdress', [offer_addr]) # Enable receiving smsg
options = {'decodehex': True, 'ttl_is_seconds': True}
msg_valid = self.SMSG_SECONDS_IN_HOUR * 1
@ -752,8 +786,8 @@ class BasicSwap(BaseApp):
swap_type=msg_buf.swap_type,
addr_from=offer_addr,
created_at=int(time.time()),
expire_at=int(time.time()) + msg_buf.time_valid,
created_at=offer_created_at,
expire_at=offer_created_at + msg_buf.time_valid,
was_sent=True,
auto_accept_bids=auto_accept_bids,)
offer.setState(OfferStates.OFFER_SENT)
@ -850,15 +884,7 @@ class BasicSwap(BaseApp):
self.mxDB.release()
def getReceiveAddressForCoin(self, coin_type):
if coin_type == Coins.PART:
new_addr = self.callcoinrpc(Coins.PART, 'getnewaddress')
elif coin_type == Coins.LTC or coin_type == Coins.BTC or coin_type == Coins.NMC:
args = []
if self.coin_clients[coin_type]['use_segwit']:
args = ['swap_receive', 'bech32']
new_addr = self.callcoinrpc(coin_type, 'getnewaddress', args)
else:
raise ValueError('Unknown coin type.')
new_addr = self.coin_clients[coin_type]['interface'].getNewAddress(self.coin_clients[coin_type]['use_segwit'])
self.log.debug('Generated new receive address %s for %s', new_addr, str(coin_type))
return new_addr
@ -2101,6 +2127,10 @@ class BasicSwap(BaseApp):
assert(len(offer_data.secret_hash) == 0), 'Unexpected data'
elif offer_data.swap_type == SwapTypes.BUYER_FIRST:
raise ValueError('TODO')
elif offer_data.swap_type == SwapTypes.XMR_SWAP:
assert(coin_from != Coins.XMR)
assert(coin_to == Coins.XMR)
logging.debug('TODO - More restrictions')
else:
raise ValueError('Unknown swap type {}.'.format(offer_data.swap_type))
@ -2461,15 +2491,17 @@ class BasicSwap(BaseApp):
def getWalletInfo(self, coin):
blockchaininfo = self.callcoinrpc(coin, 'getblockchaininfo')
walletinfo = self.callcoinrpc(coin, 'getwalletinfo')
blockchaininfo = self.coin_clients[coin]['interface'].getBlockchainInfo()
walletinfo = self.coin_clients[coin]['interface'].getWalletInfo()
scale = chainparams[coin]['decimal_places']
rv = {
'version': self.coin_clients[coin]['core_version'],
'deposit_address': self.getCachedAddressForCoin(coin),
'name': chainparams[coin]['name'].capitalize(),
'blocks': blockchaininfo['blocks'],
'balance': format8(make_int(walletinfo['balance'])),
'unconfirmed': format8(make_int(walletinfo.get('unconfirmed_balance'))),
'balance': format_amount(make_int(walletinfo['balance'], scale), scale),
'unconfirmed': format_amount(make_int(walletinfo.get('unconfirmed_balance'), scale), scale),
'synced': '{0:.2f}'.format(round(blockchaininfo['verificationprogress'], 2)),
}
return rv

@ -9,6 +9,8 @@ from .util import (
COIN,
)
XMR_COIN = 10 ** 12
class Coins(IntEnum):
PART = 1
@ -25,6 +27,7 @@ chainparams = {
'ticker': 'PART',
'message_magic': 'Bitcoin Signed Message:\n',
'blocks_target': 60 * 2,
'decimal_places': 8,
'mainnet': {
'rpcport': 51735,
'pubkey_address': 0x38,
@ -61,6 +64,7 @@ chainparams = {
'ticker': 'BTC',
'message_magic': 'Bitcoin Signed Message:\n',
'blocks_target': 60 * 10,
'decimal_places': 8,
'mainnet': {
'rpcport': 8332,
'pubkey_address': 0,
@ -95,6 +99,7 @@ chainparams = {
'ticker': 'LTC',
'message_magic': 'Litecoin Signed Message:\n',
'blocks_target': 60 * 1,
'decimal_places': 8,
'mainnet': {
'rpcport': 9332,
'pubkey_address': 48,
@ -129,6 +134,7 @@ chainparams = {
'ticker': 'NMC',
'message_magic': 'Namecoin Signed Message:\n',
'blocks_target': 60 * 10,
'decimal_places': 8,
'mainnet': {
'rpcport': 8336,
'pubkey_address': 52,
@ -162,17 +168,24 @@ chainparams = {
'name': 'monero',
'ticker': 'XMR',
'client': 'xmr',
'decimal_places': 12,
'mainnet': {
'rpcport': 18081,
'walletrpcport': 18082,
'min_amount': 100000,
'max_amount': 10000 * XMR_COIN,
},
'testnet': {
'rpcport': 28081,
'walletrpcport': 28082,
'min_amount': 100000,
'max_amount': 10000 * XMR_COIN,
},
'regtest': {
'rpcport': 18081,
'walletrpcport': 18082,
'min_amount': 100000,
'max_amount': 10000 * XMR_COIN,
}
}
}

@ -32,3 +32,7 @@ NAMECOIN_BINDIR = os.path.expanduser(os.getenv('NAMECOIN_BINDIR', ''))
NAMECOIND = os.getenv('NAMECOIND', 'namecoind' + bin_suffix)
NAMECOIN_CLI = os.getenv('NAMECOIN_CLI', 'namecoin-cli' + bin_suffix)
NAMECOIN_TX = os.getenv('NAMECOIN_TX', 'namecoin-tx' + bin_suffix)
XMR_BINDIR = os.path.expanduser(os.getenv('XMR_BINDIR', ''))
XMRD = os.getenv('XMRD', 'monerod' + bin_suffix)
XMR_WALLET_RPC = os.getenv('XMR_WALLET_RPC', 'monero-wallet-rpc' + bin_suffix)

@ -0,0 +1,51 @@
#!/usr/bin/env python3
# Copyright (c) 2015-2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from argparse import ArgumentParser
from base64 import urlsafe_b64encode
from binascii import hexlify
from getpass import getpass
from os import urandom
import hmac
def generate_salt(size):
"""Create size byte hex salt"""
return hexlify(urandom(size)).decode()
def generate_password():
"""Create 32 byte b64 password"""
return urlsafe_b64encode(urandom(32)).decode('utf-8')
def password_to_hmac(salt, password):
m = hmac.new(bytearray(salt, 'utf-8'), bytearray(password, 'utf-8'), 'SHA256')
return m.hexdigest()
def main():
parser = ArgumentParser(description='Create login credentials for a JSON-RPC user')
parser.add_argument('username', help='the username for authentication')
parser.add_argument('password', help='leave empty to generate a random password or specify "-" to prompt for password', nargs='?')
args = parser.parse_args()
if not args.password:
args.password = generate_password()
elif args.password == '-':
args.password = getpass()
# Create 16 byte hex salt
salt = generate_salt(16)
password_hmac = password_to_hmac(salt, args.password)
print('String to be appended to bitcoin.conf:')
print('rpcauth={0}:{1}${2}'.format(args.username, salt, password_hmac))
print('Your password:\n{0}'.format(args.password))
if __name__ == '__main__':
main()

@ -102,6 +102,24 @@ class BTCInterface(CoinInterface):
self.rpc_callback = make_rpc_func(coin_settings['rpcport'], coin_settings['rpcauth'])
self.txoType = CTxOut
def testDaemonRPC(self):
self.rpc_callback('getwalletinfo', [])
def getDaemonVersion(self):
return self.rpc_callback('getnetworkinfo')['version']
def getBlockchainInfo(self):
return self.rpc_callback('getblockchaininfo')
def getWalletInfo(self):
return self.rpc_callback('getwalletinfo')
def getNewAddress(self, use_segwit):
args = ['swap_receive']
if use_segwit:
args.append('bech32')
return self.rpc_callback('getnewaddress', args)
def getNewSecretKey(self):
return getSecretInt()

@ -0,0 +1,12 @@
#!/usr/bin/env python
# -*- 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 .interface_btc import BTCInterface
class NMCInterface(BTCInterface):
pass

@ -26,3 +26,6 @@ class PARTInterface(BTCInterface):
def __init__(self, coin_settings):
self.rpc_callback = make_rpc_func(coin_settings['rpcport'], coin_settings['rpcauth'])
self.txoType = CTxOutPart
def getNewAddress(self, use_segwit):
return self.rpc_callback('getnewaddress', ['swap_receive'])

@ -10,6 +10,9 @@ import logging
from .chainparams import CoinInterface
from .rpc_xmr import make_xmr_rpc_func, make_xmr_wallet_rpc_func
from .util import (
format_amount
)
XMR_COIN = 10 ** 12
@ -31,9 +34,32 @@ class XMRInterface(CoinInterface):
rpc_cb = make_xmr_rpc_func(coin_settings['rpcport'])
rpc_wallet_cb = make_xmr_wallet_rpc_func(coin_settings['walletrpcport'], coin_settings['walletrpcauth'])
self.rpc_cb = rpc_cb # Not essential
self.rpc_cb = rpc_cb
self.rpc_wallet_cb = rpc_wallet_cb
def testDaemonRPC(self):
self.rpc_wallet_cb('get_languages')
def getDaemonVersion(self):
return self.rpc_cb('get_version')['version']
def getBlockchainInfo(self):
rv = {}
rv['blocks'] = self.rpc_cb('get_block_count')['count']
rv['verificationprogress'] = 0 # TODO
return rv
def getWalletInfo(self):
rv = {}
balance_info = self.rpc_wallet_cb('get_balance')
rv['balance'] = format_amount(balance_info['unlocked_balance'], XMRInterface.exp())
rv['unconfirmed_balance'] = format_amount(balance_info['balance'] - balance_info['unlocked_balance'], XMRInterface.exp())
return rv
def getNewAddress(self, placeholder):
logging.debug('TODO - subaddress?')
return self.rpc_wallet_cb('get_address')['address']
def getNewSecretKey(self):
return edu.get_secret()

@ -46,3 +46,31 @@ message BidAcceptMessage {
bytes initiate_txid = 2;
bytes contract_script = 3;
}
message XmrOfferMessage {
uint32 coin_from = 1;
uint32 coin_to = 2;
uint64 amount_from = 3;
uint64 rate = 4;
uint64 min_bid_amount = 5;
uint64 time_valid = 6;
enum LockType {
NOT_SET = 0;
SEQUENCE_LOCK_BLOCKS = 1;
SEQUENCE_LOCK_TIME = 2;
ABS_LOCK_BLOCKS = 3;
ABS_LOCK_TIME = 4;
}
LockType lock_type = 7;
uint32 lock_value = 8;
uint32 swap_type = 9;
/* optional */
string proof_address = 10;
string proof_signature = 11;
bytes pkhash_seller = 12;
bytes secret_hash = 13;
}

@ -2,8 +2,6 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: messages.proto
import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
@ -20,7 +18,8 @@ DESCRIPTOR = _descriptor.FileDescriptor(
package='basicswap',
syntax='proto3',
serialized_options=None,
serialized_pb=_b('\n\x0emessages.proto\x12\tbasicswap\"\x84\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\"I\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\"\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\x62\x06proto3')
create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x0emessages.proto\x12\tbasicswap\"\xac\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\"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\"\xb2\x03\n\x0fXmrOfferMessage\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\x36\n\tlock_type\x18\x07 \x01(\x0e\x32#.basicswap.XmrOfferMessage.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\"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\x62\x06proto3'
)
@ -30,27 +29,81 @@ _OFFERMESSAGE_LOCKTYPE = _descriptor.EnumDescriptor(
full_name='basicswap.OfferMessage.LockType',
filename=None,
file=DESCRIPTOR,
create_key=_descriptor._internal_create_key,
values=[
_descriptor.EnumValueDescriptor(
name='NOT_SET', index=0, number=0,
serialized_options=None,
type=None),
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
name='SEQUENCE_LOCK_BLOCKS', index=1, number=1,
serialized_options=None,
type=None),
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
name='SEQUENCE_LOCK_TIME', index=2, number=2,
serialized_options=None,
type=None),
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
name='ABS_LOCK_BLOCKS', index=3, number=3,
serialized_options=None,
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
name='ABS_LOCK_TIME', index=4, number=4,
serialized_options=None,
type=None,
create_key=_descriptor._internal_create_key),
],
containing_type=None,
serialized_options=None,
serialized_start=345,
serialized_end=418,
serialized_end=458,
)
_sym_db.RegisterEnumDescriptor(_OFFERMESSAGE_LOCKTYPE)
_XMROFFERMESSAGE_LOCKTYPE = _descriptor.EnumDescriptor(
name='LockType',
full_name='basicswap.XmrOfferMessage.LockType',
filename=None,
file=DESCRIPTOR,
create_key=_descriptor._internal_create_key,
values=[
_descriptor.EnumValueDescriptor(
name='NOT_SET', index=0, number=0,
serialized_options=None,
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
name='SEQUENCE_LOCK_BLOCKS', index=1, number=1,
serialized_options=None,
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
name='SEQUENCE_LOCK_TIME', index=2, number=2,
serialized_options=None,
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
name='ABS_LOCK_BLOCKS', index=3, number=3,
serialized_options=None,
type=None,
create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
name='ABS_LOCK_TIME', index=4, number=4,
serialized_options=None,
type=None,
create_key=_descriptor._internal_create_key),
],
containing_type=None,
serialized_options=None,
serialized_start=345,
serialized_end=458,
)
_sym_db.RegisterEnumDescriptor(_XMROFFERMESSAGE_LOCKTYPE)
_OFFERMESSAGE = _descriptor.Descriptor(
name='OfferMessage',
@ -58,6 +111,7 @@ _OFFERMESSAGE = _descriptor.Descriptor(
filename=None,
file=DESCRIPTOR,
containing_type=None,
create_key=_descriptor._internal_create_key,
fields=[
_descriptor.FieldDescriptor(
name='coin_from', full_name='basicswap.OfferMessage.coin_from', index=0,
@ -65,91 +119,91 @@ _OFFERMESSAGE = _descriptor.Descriptor(
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='coin_to', full_name='basicswap.OfferMessage.coin_to', index=1,
number=2, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='amount_from', full_name='basicswap.OfferMessage.amount_from', index=2,
number=3, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='rate', full_name='basicswap.OfferMessage.rate', index=3,
number=4, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='min_bid_amount', full_name='basicswap.OfferMessage.min_bid_amount', index=4,
number=5, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='time_valid', full_name='basicswap.OfferMessage.time_valid', index=5,
number=6, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='lock_type', full_name='basicswap.OfferMessage.lock_type', index=6,
number=7, type=14, cpp_type=8, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='lock_value', full_name='basicswap.OfferMessage.lock_value', index=7,
number=8, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='swap_type', full_name='basicswap.OfferMessage.swap_type', index=8,
number=9, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='proof_address', full_name='basicswap.OfferMessage.proof_address', index=9,
number=10, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='proof_signature', full_name='basicswap.OfferMessage.proof_signature', index=10,
number=11, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='pkhash_seller', full_name='basicswap.OfferMessage.pkhash_seller', index=11,
number=12, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
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),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='secret_hash', full_name='basicswap.OfferMessage.secret_hash', index=12,
number=13, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
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),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
],
extensions=[
],
@ -164,7 +218,7 @@ _OFFERMESSAGE = _descriptor.Descriptor(
oneofs=[
],
serialized_start=30,
serialized_end=418,
serialized_end=458,
)
@ -174,49 +228,50 @@ _BIDMESSAGE = _descriptor.Descriptor(
filename=None,
file=DESCRIPTOR,
containing_type=None,
create_key=_descriptor._internal_create_key,
fields=[
_descriptor.FieldDescriptor(
name='offer_msg_id', full_name='basicswap.BidMessage.offer_msg_id', index=0,
number=1, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
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),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='time_valid', full_name='basicswap.BidMessage.time_valid', index=1,
number=2, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='amount', full_name='basicswap.BidMessage.amount', index=2,
number=3, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='pkhash_buyer', full_name='basicswap.BidMessage.pkhash_buyer', index=3,
number=4, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
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),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='proof_address', full_name='basicswap.BidMessage.proof_address', index=4,
number=5, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='proof_signature', full_name='basicswap.BidMessage.proof_signature', index=5,
number=6, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
],
extensions=[
],
@ -229,8 +284,8 @@ _BIDMESSAGE = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
serialized_start=421,
serialized_end=561,
serialized_start=461,
serialized_end=601,
)
@ -240,33 +295,151 @@ _BIDACCEPTMESSAGE = _descriptor.Descriptor(
filename=None,
file=DESCRIPTOR,
containing_type=None,
create_key=_descriptor._internal_create_key,
fields=[
_descriptor.FieldDescriptor(
name='bid_msg_id', full_name='basicswap.BidAcceptMessage.bid_msg_id', index=0,
number=1, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
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),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='initiate_txid', full_name='basicswap.BidAcceptMessage.initiate_txid', index=1,
number=2, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
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),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='contract_script', full_name='basicswap.BidAcceptMessage.contract_script', index=2,
number=3, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
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=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=603,
serialized_end=689,
)
_XMROFFERMESSAGE = _descriptor.Descriptor(
name='XmrOfferMessage',
full_name='basicswap.XmrOfferMessage',
filename=None,
file=DESCRIPTOR,
containing_type=None,
create_key=_descriptor._internal_create_key,
fields=[
_descriptor.FieldDescriptor(
name='coin_from', full_name='basicswap.XmrOfferMessage.coin_from', index=0,
number=1, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
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='coin_to', full_name='basicswap.XmrOfferMessage.coin_to', index=1,
number=2, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
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='amount_from', full_name='basicswap.XmrOfferMessage.amount_from', index=2,
number=3, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
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='rate', full_name='basicswap.XmrOfferMessage.rate', index=3,
number=4, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
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='min_bid_amount', full_name='basicswap.XmrOfferMessage.min_bid_amount', index=4,
number=5, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
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='time_valid', full_name='basicswap.XmrOfferMessage.time_valid', index=5,
number=6, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
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='lock_type', full_name='basicswap.XmrOfferMessage.lock_type', index=6,
number=7, type=14, cpp_type=8, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='lock_value', full_name='basicswap.XmrOfferMessage.lock_value', index=7,
number=8, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
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='swap_type', full_name='basicswap.XmrOfferMessage.swap_type', index=8,
number=9, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
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='proof_address', full_name='basicswap.XmrOfferMessage.proof_address', index=9,
number=10, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
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='proof_signature', full_name='basicswap.XmrOfferMessage.proof_signature', index=10,
number=11, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
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='pkhash_seller', full_name='basicswap.XmrOfferMessage.pkhash_seller', 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),
_descriptor.FieldDescriptor(
name='secret_hash', full_name='basicswap.XmrOfferMessage.secret_hash', index=12,
number=13, 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=[
],
nested_types=[],
enum_types=[
_XMROFFERMESSAGE_LOCKTYPE,
],
serialized_options=None,
is_extendable=False,
@ -274,37 +447,47 @@ _BIDACCEPTMESSAGE = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
serialized_start=563,
serialized_end=649,
serialized_start=692,
serialized_end=1126,
)
_OFFERMESSAGE.fields_by_name['lock_type'].enum_type = _OFFERMESSAGE_LOCKTYPE
_OFFERMESSAGE_LOCKTYPE.containing_type = _OFFERMESSAGE
_XMROFFERMESSAGE.fields_by_name['lock_type'].enum_type = _XMROFFERMESSAGE_LOCKTYPE
_XMROFFERMESSAGE_LOCKTYPE.containing_type = _XMROFFERMESSAGE
DESCRIPTOR.message_types_by_name['OfferMessage'] = _OFFERMESSAGE
DESCRIPTOR.message_types_by_name['BidMessage'] = _BIDMESSAGE
DESCRIPTOR.message_types_by_name['BidAcceptMessage'] = _BIDACCEPTMESSAGE
DESCRIPTOR.message_types_by_name['XmrOfferMessage'] = _XMROFFERMESSAGE
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
OfferMessage = _reflection.GeneratedProtocolMessageType('OfferMessage', (_message.Message,), dict(
DESCRIPTOR = _OFFERMESSAGE,
__module__ = 'messages_pb2'
OfferMessage = _reflection.GeneratedProtocolMessageType('OfferMessage', (_message.Message,), {
'DESCRIPTOR' : _OFFERMESSAGE,
'__module__' : 'messages_pb2'
# @@protoc_insertion_point(class_scope:basicswap.OfferMessage)
))
})
_sym_db.RegisterMessage(OfferMessage)
BidMessage = _reflection.GeneratedProtocolMessageType('BidMessage', (_message.Message,), dict(
DESCRIPTOR = _BIDMESSAGE,
__module__ = 'messages_pb2'
BidMessage = _reflection.GeneratedProtocolMessageType('BidMessage', (_message.Message,), {
'DESCRIPTOR' : _BIDMESSAGE,
'__module__' : 'messages_pb2'
# @@protoc_insertion_point(class_scope:basicswap.BidMessage)
))
})
_sym_db.RegisterMessage(BidMessage)
BidAcceptMessage = _reflection.GeneratedProtocolMessageType('BidAcceptMessage', (_message.Message,), dict(
DESCRIPTOR = _BIDACCEPTMESSAGE,
__module__ = 'messages_pb2'
BidAcceptMessage = _reflection.GeneratedProtocolMessageType('BidAcceptMessage', (_message.Message,), {
'DESCRIPTOR' : _BIDACCEPTMESSAGE,
'__module__' : 'messages_pb2'
# @@protoc_insertion_point(class_scope:basicswap.BidAcceptMessage)
))
})
_sym_db.RegisterMessage(BidAcceptMessage)
XmrOfferMessage = _reflection.GeneratedProtocolMessageType('XmrOfferMessage', (_message.Message,), {
'DESCRIPTOR' : _XMROFFERMESSAGE,
'__module__' : 'messages_pb2'
# @@protoc_insertion_point(class_scope:basicswap.XmrOfferMessage)
})
_sym_db.RegisterMessage(XmrOfferMessage)
# @@protoc_insertion_point(module_scope)

@ -18,14 +18,15 @@ from xmlrpc.client import (
from .util import jsonDecimal
def waitForRPC(rpc_func, wallet=None):
for i in range(5):
def waitForRPC(rpc_func, wallet=None, max_tries=7):
for i in range(max_tries + 1):
try:
rpc_func('getwalletinfo')
return
except Exception as ex:
logging.warning('Can\'t connect to daemon RPC: %s. Trying again in %d second/s.', str(ex), (1 + i))
time.sleep(1 + i)
if i < max_tries:
logging.warning('Can\'t connect to RPC: %s. Retrying in %d second/s.', str(ex), (i + 1))
time.sleep(i + 1)
raise ValueError('waitForRPC failed')

@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018-2019 tecnovert
# Copyright (c) 2018-2020 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import decimal
import json
import hashlib
from .contrib.segwit_addr import bech32_decode, convertbits, bech32_encode
@ -12,7 +11,6 @@ from .contrib.segwit_addr import bech32_decode, convertbits, bech32_encode
OP_1 = 0x51
OP_16 = 0x60
COIN = 100000000
DCOIN = decimal.Decimal(COIN)
def assert_cond(v, err='Bad opcode'):
@ -34,10 +32,6 @@ def toBool(s):
return s.lower() in ["1", "true"]
def dquantize(n, places=8):
return n.quantize(decimal.Decimal(10) ** -places)
def jsonDecimal(obj):
if isinstance(obj, decimal.Decimal):
return str(obj)
@ -229,13 +223,13 @@ def getCompactSizeLen(v):
raise ValueError('Value too large')
def make_int(v, precision=8, r=0): # r = 0, no rounding, fail, r > 0 round up, r < 0 floor
def make_int(v, scale=8, r=0): # r = 0, no rounding, fail, r > 0 round up, r < 0 floor
if type(v) == float:
v = str(v)
elif type(v) == int:
return v * 10 ** precision
return v * 10 ** scale
ep = 10 ** precision
ep = 10 ** scale
have_dp = False
rv = 0
for c in v:
@ -264,7 +258,7 @@ def make_int(v, precision=8, r=0): # r = 0, no rounding, fail, r > 0 round up,
return rv
def validate_amount(amount, precision=8):
def validate_amount(amount, scale=8):
str_amount = str(amount)
has_decimal = False
for c in str_amount:
@ -275,21 +269,21 @@ def validate_amount(amount, precision=8):
raise ValueError('Invalid amount')
ar = str_amount.split('.')
if len(ar) > 1 and len(ar[1]) > precision:
if len(ar) > 1 and len(ar[1]) > scale:
raise ValueError('Too many decimal places in amount {}'.format(str_amount))
return True
def format_amount(i, display_precision, precision=None):
if precision is None:
precision = display_precision
ep = 10 ** precision
def format_amount(i, display_scale, scale=None):
if scale is None:
scale = display_scale
ep = 10 ** scale
n = abs(i)
quotient = n // ep
remainder = n % ep
if display_precision != precision:
remainder %= (10 ** display_precision)
rv = '{}.{:0>{prec}}'.format(quotient, remainder, prec=display_precision)
if display_scale != scale:
remainder %= (10 ** display_scale)
rv = '{}.{:0>{prec}}'.format(quotient, remainder, prec=display_scale)
if i < 0:
rv = '-' + rv
return rv

@ -46,6 +46,7 @@ known_coins = {
'litecoin': '0.18.1',
'bitcoin': '0.20.1',
'namecoin': '0.18.0',
'monero': '0.17.0.1',
}
logger = logging.getLogger()
@ -124,6 +125,15 @@ def prepareCore(coin, version, settings, data_dir):
os_dir_name = 'linux'
os_name = 'linux'
if coin == 'monero':
url = 'https://downloads.getmonero.org/cli/monero-linux-x64-v${}.tar.bz2'.format(version)
release_path = os.path.join(bin_dir, release_filename)
if not os.path.exists(release_path):
downloadFile(release_url, release_path)
raise ValueError('TODO')
release_filename = '{}-{}-{}'.format(coin, version, BIN_ARCH)
if coin == 'particl':
signing_key_name = 'tecnovert'

@ -45,7 +45,7 @@ def startDaemon(node_dir, bin_dir, daemon_bin, opts=[]):
daemon_bin = os.path.expanduser(os.path.join(bin_dir, daemon_bin))
args = [daemon_bin, '-datadir=' + os.path.expanduser(node_dir)] + opts
logger.info('Starting node ' + daemon_bin + ' ' + '-datadir=' + node_dir)
logging.info('Starting node ' + daemon_bin + ' ' + '-datadir=' + node_dir)
return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@ -118,9 +118,13 @@ def runClient(fp, data_dir, chain):
closed_pids = []
for d in daemons:
int_pid = d.pid
logger.info('Terminating {}'.format(int_pid))
logging.info('Interrupting {}'.format(int_pid))
try:
d.send_signal(signal.SIGINT)
except Exception as e:
logging.info('Interrupting %d, error %s', d.pid, str(e))
for d in daemons:
try:
d.terminate()
d.wait(timeout=120)
if d.stdout:
d.stdout.close()

@ -24,6 +24,7 @@ setuptools.setup(
"Operating System :: Linux",
],
install_requires=[
"wheel",
"pyzmq",
"protobuf",
"sqlalchemy",

@ -5,6 +5,13 @@
# Distributed under the MIT software license, see the accompanying
# file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
import os
TEST_HTTP_HOST = os.getenv('TEST_HTTP_HOST', '127.0.0.1') # Set to 0.0.0.0 when used in docker
TEST_HTTP_PORT = 1800
def checkForks(ro):
if 'bip9_softforks' in ro:
assert(ro['bip9_softforks']['csv']['status'] == 'active')

@ -44,6 +44,10 @@ from basicswap.contrib.key import (
from basicswap.http_server import (
HttpThread,
)
from tests.basicswap.common import (
TEST_HTTP_HOST,
TEST_HTTP_PORT,
)
from bin.basicswap_run import startDaemon
import basicswap.config as cfg
@ -58,7 +62,6 @@ BASE_PORT = 14792
BASE_RPC_PORT = 19792
BASE_ZMQ_PORT = 20792
PREFIX_SECRET_KEY_REGTEST = 0x2e
TEST_HTML_PORT = 1800
NMC_NODE = 3
BTC_NODE = 4
stop_test = False
@ -278,9 +281,8 @@ class Test(unittest.TestCase):
print('nmcRpc', ro)
cls.http_threads = []
host = '0.0.0.0' # All interfaces (docker)
for i in range(3):
t = HttpThread(cls.swap_clients[i].fp, host, TEST_HTML_PORT + i, False, cls.swap_clients[i])
t = HttpThread(cls.swap_clients[i].fp, TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, cls.swap_clients[i])
cls.http_threads.append(t)
t.start()

@ -50,6 +50,8 @@ from basicswap.http_server import (
)
from tests.basicswap.common import (
checkForks,
TEST_HTTP_HOST,
TEST_HTTP_PORT,
)
from bin.basicswap_run import startDaemon
@ -63,7 +65,6 @@ BASE_PORT = 14792
BASE_RPC_PORT = 19792
BASE_ZMQ_PORT = 20792
PREFIX_SECRET_KEY_REGTEST = 0x2e
TEST_HTML_PORT = 1800
LTC_NODE = 3
BTC_NODE = 4
stop_test = False
@ -247,11 +248,12 @@ class Test(unittest.TestCase):
with open(settings_path) as fs:
settings = json.load(fs)
fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w')
cls.swap_clients.append(BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i)))
cls.swap_clients[-1].setDaemonPID(Coins.BTC, cls.daemons[0].pid)
cls.swap_clients[-1].setDaemonPID(Coins.LTC, cls.daemons[1].pid)
cls.swap_clients[-1].setDaemonPID(Coins.PART, cls.daemons[2 + i].pid)
cls.swap_clients[-1].start()
sc = BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i))
sc.setDaemonPID(Coins.BTC, cls.daemons[0].pid)
sc.setDaemonPID(Coins.LTC, cls.daemons[1].pid)
sc.setDaemonPID(Coins.PART, cls.daemons[2 + i].pid)
sc.start()
cls.swap_clients.append(sc)
cls.swap_clients[0].callrpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb'])
cls.swap_clients[1].callrpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true'])
cls.swap_clients[1].callrpc('getnewextaddress', ['lblExtTest'])
@ -278,9 +280,8 @@ class Test(unittest.TestCase):
print('ltcRpc', ro)
cls.http_threads = []
host = '0.0.0.0' # All interfaces (docker)
for i in range(3):
t = HttpThread(cls.swap_clients[i].fp, host, TEST_HTML_PORT + i, False, cls.swap_clients[i])
t = HttpThread(cls.swap_clients[i].fp, TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, cls.swap_clients[i])
cls.http_threads.append(t)
t.start()
@ -300,8 +301,12 @@ class Test(unittest.TestCase):
for c in cls.swap_clients:
c.fp.close()
for d in cls.daemons:
logging.info('Terminating %d', d.pid)
d.terminate()
logging.info('Interrupting %d', d.pid)
try:
d.send_signal(signal.SIGINT)
except Exception as e:
logging.info('Interrupting %d, error %s', d.pid, str(e))
for d in cls.daemons:
d.wait(timeout=10)
if d.stdout:
d.stdout.close()

@ -7,13 +7,15 @@
import os
import sys
import unittest
import json
import logging
import shutil
import time
import shutil
import signal
import logging
import unittest
import traceback
import threading
import subprocess
from urllib.request import urlopen
from coincurve.ecdsaotves import (
ecdsaotves_enc_sign,
@ -37,71 +39,100 @@ from basicswap.util import (
COIN,
toWIF,
dumpje,
make_int,
)
from basicswap.rpc import (
callrpc,
callrpc_cli,
waitForRPC,
)
from basicswap.rpc_xmr import (
callrpc_xmr_na,
callrpc_xmr,
)
from basicswap.interface_xmr import (
XMR_COIN,
)
from basicswap.contrib.key import (
ECKey,
)
from basicswap.http_server import (
HttpThread,
)
from tests.basicswap.common import (
checkForks,
TEST_HTTP_HOST,
TEST_HTTP_PORT,
)
from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
from bin.basicswap_run import startDaemon
logger = logging.getLogger()
logger.level = logging.DEBUG
if not len(logger.handlers):
logger.addHandler(logging.StreamHandler(sys.stdout))
NUM_NODES = 3
NUM_XMR_NODES = 3
NUM_BTC_NODES = 3
TEST_DIR = cfg.TEST_DATADIRS
BASE_PORT = 14792
BASE_RPC_PORT = 19792
BASE_ZMQ_PORT = 20792
BTC_BASE_PORT = 114792
BTC_BASE_RPC_PORT = 119792
BTC_BASE_ZMQ_PORT = 120792
XMR_BASE_P2P_PORT = 17792
XMR_BASE_RPC_PORT = 21792
XMR_BASE_ZMQ_PORT = 22792
XMR_BASE_WALLET_RPC_PORT = 23792
PREFIX_SECRET_KEY_REGTEST = 0x2e
TEST_HTML_PORT = 1800
stop_test = False
def prepareOtherDir(datadir, nodeId, conf_file='litecoin.conf'):
node_dir = os.path.join(datadir, str(nodeId))
def prepareXmrDataDir(datadir, node_id, conf_file):
node_dir = os.path.join(datadir, 'xmr_' + str(node_id))
if not os.path.exists(node_dir):
os.makedirs(node_dir)
filePath = os.path.join(node_dir, conf_file)
with open(filePath, 'w+') as fp:
cfg_file_path = os.path.join(node_dir, conf_file)
if os.path.exists(cfg_file_path):
return
with open(cfg_file_path, 'w+') as fp:
fp.write('regtest=1\n')
fp.write('[regtest]\n')
fp.write('port=' + str(BASE_PORT + nodeId) + '\n')
fp.write('rpcport=' + str(BASE_RPC_PORT + nodeId) + '\n')
fp.write('daemon=0\n')
fp.write('printtoconsole=0\n')
fp.write('server=1\n')
fp.write('discover=0\n')
fp.write('listenonion=0\n')
fp.write('bind=127.0.0.1\n')
fp.write('findpeers=0\n')
fp.write('debug=1\n')
fp.write('debugexclude=libevent\n')
fp.write('fallbackfee=0.0002\n')
fp.write('acceptnonstdtxn=0\n')
fp.write('keep-fakechain=1\n')
fp.write('data-dir={}\n'.format(node_dir))
fp.write('fixed-difficulty=1\n')
# fp.write('offline=1\n')
fp.write('p2p-bind-port={}\n'.format(XMR_BASE_P2P_PORT + node_id))
fp.write('rpc-bind-port={}\n'.format(XMR_BASE_RPC_PORT + node_id))
fp.write('p2p-bind-ip=127.0.0.1\n')
fp.write('rpc-bind-ip=127.0.0.1\n')
fp.write('zmq-rpc-bind-port={}\n'.format(XMR_BASE_ZMQ_PORT + node_id))
fp.write('zmq-rpc-bind-ip=127.0.0.1\n')
for i in range(0, NUM_XMR_NODES):
if node_id == i:
continue
fp.write('add-exclusive-node=127.0.0.1:{}\n'.format(XMR_BASE_P2P_PORT + i))
def prepareDir(datadir, nodeId, network_key, network_pubkey):
node_dir = os.path.join(datadir, str(nodeId))
def prepareDataDir(datadir, node_id, conf_file, dir_prefix, base_p2p_port=BASE_PORT, base_rpc_port=BASE_RPC_PORT):
node_dir = os.path.join(datadir, dir_prefix + str(node_id))
if not os.path.exists(node_dir):
os.makedirs(node_dir)
filePath = os.path.join(node_dir, 'particl.conf')
with open(filePath, 'w+') as fp:
cfg_file_path = os.path.join(node_dir, conf_file)
if os.path.exists(cfg_file_path):
return
with open(cfg_file_path, 'w+') as fp:
fp.write('regtest=1\n')
fp.write('[regtest]\n')
fp.write('port=' + str(BASE_PORT + nodeId) + '\n')
fp.write('rpcport=' + str(BASE_RPC_PORT + nodeId) + '\n')
fp.write('port=' + str(base_p2p_port + node_id) + '\n')
fp.write('rpcport=' + str(base_rpc_port + node_id) + '\n')
salt = generate_salt(16)
fp.write('rpcauth={}:{}${}\n'.format('test' + str(node_id), salt, password_to_hmac(salt, 'test_pass' + str(node_id))))
fp.write('daemon=0\n')
fp.write('printtoconsole=0\n')
@ -109,62 +140,100 @@ def prepareDir(datadir, nodeId, network_key, network_pubkey):
fp.write('discover=0\n')
fp.write('listenonion=0\n')
fp.write('bind=127.0.0.1\n')
fp.write('findpeers=0\n')
fp.write('debug=1\n')
fp.write('debugexclude=libevent\n')
fp.write('zmqpubsmsg=tcp://127.0.0.1:' + str(BASE_ZMQ_PORT + nodeId) + '\n')
fp.write('fallbackfee=0.01\n')
fp.write('acceptnonstdtxn=0\n')
fp.write('minstakeinterval=5\n')
fp.write('txindex=1\n')
fp.write('findpeers=0\n')
# minstakeinterval=5 # Using walletsettings stakelimit instead
if base_p2p_port == BASE_PORT: # Particl
fp.write('zmqpubsmsg=tcp://127.0.0.1:{}\n'.format(BASE_ZMQ_PORT + node_id))
for i in range(0, NUM_NODES):
if nodeId == i:
if node_id == i:
continue
fp.write('addnode=127.0.0.1:%d\n' % (BASE_PORT + i))
fp.write('addnode=127.0.0.1:{}\n'.format(base_p2p_port + i))
def startXmrDaemon(node_dir, bin_dir, daemon_bin, opts=[]):
daemon_bin = os.path.expanduser(os.path.join(bin_dir, daemon_bin))
args = [daemon_bin, '--config-file=' + os.path.join(os.path.expanduser(node_dir), 'monerod.conf')] + opts
logging.info('Starting node {} --data-dir={}'.format(daemon_bin, node_dir))
if nodeId < 2:
fp.write('spentindex=1\n')
fp.write('txindex=1\n')
return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
basicswap_dir = os.path.join(datadir, str(nodeId), 'basicswap')
def startXmrWalletRPC(node_dir, bin_dir, wallet_bin, node_id, opts=[]):
daemon_bin = os.path.expanduser(os.path.join(bin_dir, wallet_bin))
data_dir = os.path.expanduser(node_dir)
args = [daemon_bin]
args += ['--daemon-address=localhost:{}'.format(XMR_BASE_RPC_PORT + node_id)]
args += ['--no-dns']
args += ['--rpc-bind-port={}'.format(XMR_BASE_WALLET_RPC_PORT + node_id)]
args += ['--wallet-dir={}'.format(os.path.join(data_dir, 'wallets'))]
args += ['--log-file={}'.format(os.path.join(data_dir, 'wallet.log'))]
args += ['--rpc-login=test{0}:test_pass{0}'.format(node_id)]
args += ['--shared-ringdb-dir={}'.format(os.path.join(data_dir, 'shared-ringdb'))]
args += opts
logging.info('Starting daemon {} --wallet-dir={}'.format(daemon_bin, node_dir))
wallet_stdout = open(os.path.join(data_dir, 'wallet_stdout.log'), 'w')
wallet_stderr = open(os.path.join(data_dir, 'wallet_stderr.log'), 'w')
return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=wallet_stdout, stderr=wallet_stderr, cwd=data_dir)
def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey):
basicswap_dir = os.path.join(datadir, 'basicswap_' + str(node_id))
if not os.path.exists(basicswap_dir):
os.makedirs(basicswap_dir)
ltcdatadir = os.path.join(datadir, str(LTC_NODE))
btcdatadir = os.path.join(datadir, str(BTC_NODE))
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
settings = {
'zmqhost': 'tcp://127.0.0.1',
'zmqport': BASE_ZMQ_PORT + nodeId,
'zmqport': BASE_ZMQ_PORT + node_id,
'htmlhost': 'localhost',
'htmlport': 12700 + nodeId,
'htmlport': 12700 + node_id,
'network_key': network_key,
'network_pubkey': network_pubkey,
'chainclients': {
'particl': {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': BASE_RPC_PORT + nodeId,
'datadir': node_dir,
'rpcport': BASE_RPC_PORT + node_id,
'rpcuser': 'test' + str(node_id),
'rpcpassword': 'test_pass' + str(node_id),
'datadir': os.path.join(datadir, 'part_' + str(node_id)),
'bindir': cfg.PARTICL_BINDIR,
'blocks_confirmed': 2, # Faster testing
},
'litecoin': {
'monero': {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': BASE_RPC_PORT + LTC_NODE,
'datadir': ltcdatadir,
'bindir': cfg.LITECOIN_BINDIR,
# 'use_segwit': True,
'rpcport': XMR_BASE_RPC_PORT + node_id,
'walletrpcport': XMR_BASE_WALLET_RPC_PORT + node_id,
'walletrpcuser': 'test' + str(node_id),
'walletrpcpassword': 'test_pass' + str(node_id),
'datadir': os.path.join(datadir, 'xmr_' + str(node_id)),
'bindir': cfg.XMR_BINDIR,
},
'bitcoin': {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': BASE_RPC_PORT + BTC_NODE,
'datadir': btcdatadir,
'rpcport': BTC_BASE_RPC_PORT + node_id,
'rpcuser': 'test' + str(node_id),
'rpcpassword': 'test_pass' + str(node_id),
'datadir': os.path.join(datadir, 'btc_' + str(node_id)),
'bindir': cfg.BITCOIN_BINDIR,
'use_segwit': True,
}
},
'check_progress_seconds': 2,
'check_watched_seconds': 4,
@ -173,16 +242,27 @@ def prepareDir(datadir, nodeId, network_key, network_pubkey):
'min_delay_auto_accept': 1,
'max_delay_auto_accept': 5
}
with open(settings_path, 'w') as fp:
json.dump(settings, fp, indent=4)
def partRpc(cmd, node_id=0):
return callrpc_cli(cfg.PARTICL_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(node_id)), 'regtest', cmd, cfg.PARTICL_CLI)
return callrpc_cli(cfg.PARTICL_BINDIR, os.path.join(TEST_DIR, 'part_' + str(node_id)), 'regtest', cmd, cfg.PARTICL_CLI)
def btcRpc(cmd, node_id=0):
return callrpc_cli(cfg.BITCOIN_BINDIR, os.path.join(TEST_DIR, 'btc_' + str(node_id)), 'regtest', cmd, cfg.BITCOIN_CLI)
def make_rpc_func(node_id, base_rpc_port=BASE_RPC_PORT):
node_id = node_id
auth = 'test{0}:test_pass{0}'.format(node_id)
def btcRpc(cmd):
return callrpc_cli(cfg.BITCOIN_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)), 'regtest', cmd, cfg.BITCOIN_CLI)
def rpc_func(method, params=None, wallet=None):
nonlocal node_id, auth
return callrpc(base_rpc_port + node_id, auth, method, params, wallet)
return rpc_func
def signal_handler(sig, frame):
@ -191,21 +271,47 @@ def signal_handler(sig, frame):
stop_test = True
def run_loop(self):
def waitForXMRNode(rpc_offset, max_tries=7):
for i in range(max_tries + 1):
try:
callrpc_xmr_na(XMR_BASE_RPC_PORT + rpc_offset, 'get_block_count')
return
except Exception as ex:
if i < max_tries:
logging.warning('Can\'t connect to XMR RPC: %s. Retrying in %d second/s.', str(ex), (i + 1))
time.sleep(i + 1)
raise ValueError('waitForXMRNode failed')
def waitForXMRWallet(rpc_offset, auth, max_tries=7):
for i in range(max_tries + 1):
try:
callrpc_xmr(XMR_BASE_WALLET_RPC_PORT + rpc_offset, auth, 'get_languages')
return
except Exception as ex:
if i < max_tries:
logging.warning('Can\'t connect to XMR wallet RPC: %s. Retrying in %d second/s.', str(ex), (i + 1))
time.sleep(i + 1)
raise ValueError('waitForXMRWallet failed')
def callnoderpc(node_id, method, params=[], wallet=None, base_rpc_port=BASE_RPC_PORT):
auth = 'test{0}:test_pass{0}'.format(node_id)
return callrpc(base_rpc_port + node_id, auth, method, params, wallet)
def run_loop(cls):
global stop_test
while not stop_test:
time.sleep(1)
for c in self.swap_clients:
for c in cls.swap_clients:
c.update()
btcRpc('generatetoaddress 1 {}'.format(self.btc_addr))
if cls.btc_addr is not None:
btcRpc('generatetoaddress 1 {}'.format(cls.btc_addr))
def checkForks(ro):
if 'bip9_softforks' in ro:
assert(ro['bip9_softforks']['csv']['status'] == 'active')
assert(ro['bip9_softforks']['segwit']['status'] == 'active')
else:
assert(ro['softforks']['csv']['active'])
assert(ro['softforks']['segwit']['active'])
if cls.xmr_addr is not None:
callrpc_xmr_na(XMR_BASE_RPC_PORT + 0, 'generateblocks', {'wallet_address': cls.xmr_addr, 'amount_of_blocks': 1})
time.sleep(1.0)
class Test(unittest.TestCase):
@ -214,32 +320,210 @@ class Test(unittest.TestCase):
def setUpClass(cls):
super(Test, cls).setUpClass()
cls.update_thread = None
cls.http_threads = []
cls.swap_clients = []
cls.part_daemons = []
cls.btc_daemons = []
cls.xmr_daemons = []
cls.xmr_wallet_auth = []
cls.part_stakelimit = 0
cls.xmr_addr = None
signal.signal(signal.SIGINT, signal_handler)
cls.update_thread = threading.Thread(target=run_loop, args=(cls,))
cls.update_thread.start()
cls.btc_addr = None
logger.propagate = False
logger.handlers = []
logger.setLevel(logging.INFO) # DEBUG shows many messages from requests.post
formatter = logging.Formatter('%(asctime)s %(levelname)s : %(message)s')
stream_stdout = logging.StreamHandler()
stream_stdout.setFormatter(formatter)
logger.addHandler(stream_stdout)
if os.path.isdir(TEST_DIR):
logging.info('Removing ' + TEST_DIR)
shutil.rmtree(TEST_DIR)
if not os.path.exists(TEST_DIR):
os.makedirs(TEST_DIR)
cls.stream_fp = logging.FileHandler(os.path.join(TEST_DIR, 'test.log'))
cls.stream_fp.setFormatter(formatter)
logger.addHandler(cls.stream_fp)
try:
logging.info('Preparing coin nodes.')
for i in range(NUM_NODES):
prepareDataDir(TEST_DIR, i, 'particl.conf', 'part_')
cls.part_daemons.append(startDaemon(os.path.join(TEST_DIR, 'part_' + str(i)), cfg.PARTICL_BINDIR, cfg.PARTICLD))
logging.info('Started %s %d', cfg.PARTICLD, cls.part_daemons[-1].pid)
waitForRPC(make_rpc_func(i))
for i in range(NUM_BTC_NODES):
prepareDataDir(TEST_DIR, i, 'bitcoin.conf', 'btc_', base_p2p_port=BTC_BASE_PORT, base_rpc_port=BTC_BASE_RPC_PORT)
cls.btc_daemons.append(startDaemon(os.path.join(TEST_DIR, 'btc_' + str(i)), cfg.BITCOIN_BINDIR, cfg.BITCOIND))
logging.info('Started %s %d', cfg.BITCOIND, cls.part_daemons[-1].pid)
waitForRPC(make_rpc_func(i, base_rpc_port=BTC_BASE_RPC_PORT))
for i in range(NUM_XMR_NODES):
prepareXmrDataDir(TEST_DIR, i, 'monerod.conf')
cls.xmr_daemons.append(startXmrDaemon(os.path.join(TEST_DIR, 'xmr_' + str(i)), cfg.XMR_BINDIR, cfg.XMRD))
logging.info('Started %s %d', cfg.XMRD, cls.xmr_daemons[-1].pid)
waitForXMRNode(i)
cls.xmr_daemons.append(startXmrWalletRPC(os.path.join(TEST_DIR, 'xmr_' + str(i)), cfg.XMR_BINDIR, cfg.XMR_WALLET_RPC, i))
for i in range(NUM_XMR_NODES):
cls.xmr_wallet_auth.append(('test{0}'.format(i), 'test_pass{0}'.format(i)))
logging.info('Creating XMR wallet %i', i)
waitForXMRWallet(i, cls.xmr_wallet_auth[i])
cls.callxmrnodewallet(cls, i, 'create_wallet', {'filename': 'testwallet', 'language': 'English'})
cls.callxmrnodewallet(cls, i, 'open_wallet', {'filename': 'testwallet'})
logging.info('Preparing swap clients.')
eckey = ECKey()
eckey.generate()
cls.network_key = toWIF(PREFIX_SECRET_KEY_REGTEST, eckey.get_bytes())
cls.network_pubkey = eckey.get_pubkey().get_bytes().hex()
for i in range(NUM_NODES):
prepare_swapclient_dir(TEST_DIR, i, cls.network_key, cls.network_pubkey)
basicswap_dir = os.path.join(os.path.join(TEST_DIR, 'basicswap_' + str(i)))
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
with open(settings_path) as fs:
settings = json.load(fs)
fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w')
sc = BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i))
sc.setDaemonPID(Coins.BTC, cls.btc_daemons[i].pid)
sc.setDaemonPID(Coins.PART, cls.part_daemons[i].pid)
sc.start()
cls.swap_clients.append(sc)
logging.info('Initialising coin networks.')
cls.swap_clients[0].callrpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb'])
cls.swap_clients[1].callrpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true'])
cls.swap_clients[1].callrpc('getnewextaddress', ['lblExtTest'])
cls.swap_clients[1].callrpc('rescanblockchain')
for i in range(3):
t = HttpThread(cls.swap_clients[i].fp, TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, cls.swap_clients[i])
cls.http_threads.append(t)
t.start()
cls.btc_addr = callnoderpc(0, 'getnewaddress', ['mining_addr', 'bech32'], base_rpc_port=BTC_BASE_RPC_PORT)
cls.xmr_addr = cls.callxmrnodewallet(cls, 0, 'get_address')['address']
num_blocks = 500
logging.info('Mining %d bitcoin blocks to %s', num_blocks, cls.btc_addr)
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.btc_addr], base_rpc_port=BTC_BASE_RPC_PORT)
checkForks(callnoderpc(0, 'getblockchaininfo', base_rpc_port=BTC_BASE_RPC_PORT))
if callrpc_xmr_na(XMR_BASE_RPC_PORT + 0, 'get_block_count')['count'] < num_blocks:
logging.info('Mining %d Monero blocks.', num_blocks)
callrpc_xmr_na(XMR_BASE_RPC_PORT + 0, 'generateblocks', {'wallet_address': cls.xmr_addr, 'amount_of_blocks': num_blocks})
rv = callrpc_xmr_na(XMR_BASE_RPC_PORT + 0, 'get_block_count')
logging.info('XMR blocks: %d', rv['count'])
logging.info('Starting update thread.')
signal.signal(signal.SIGINT, signal_handler)
cls.update_thread = threading.Thread(target=run_loop, args=(cls,))
cls.update_thread.start()
except Exception:
traceback.print_exc()
Test.tearDownClass()
raise ValueError('setUpClass() failed.')
@classmethod
def tearDownClass(cls):
global stop_test
logging.info('Finalising')
stop_test = True
cls.update_thread.join()
if cls.update_thread is not None:
try:
cls.update_thread.join()
except Exception:
logging.info('Failed to join update_thread')
cls.update_thread = None
for t in cls.http_threads:
t.stop()
t.join()
for c in cls.swap_clients:
c.fp.close()
for d in cls.xmr_daemons:
logging.info('Interrupting %d', d.pid)
try:
d.send_signal(signal.SIGINT)
except Exception as e:
logging.info('Interrupting %d, error %s', d.pid, str(e))
for d in cls.xmr_daemons:
try:
d.wait(timeout=20)
if d.stdout:
d.stdout.close()
if d.stderr:
d.stderr.close()
if d.stdin:
d.stdin.close()
except Exception as e:
logging.info('Closing %d, error %s', d.pid, str(e))
for d in cls.part_daemons + cls.btc_daemons:
logging.info('Interrupting %d', d.pid)
try:
d.send_signal(signal.SIGINT)
except Exception as e:
logging.info('Interrupting %d, error %s', d.pid, str(e))
for d in cls.part_daemons + cls.btc_daemons:
try:
d.wait(timeout=20)
if d.stdout:
d.stdout.close()
if d.stderr:
d.stderr.close()
if d.stdin:
d.stdin.close()
except Exception as e:
logging.info('Closing %d, error %s', d.pid, str(e))
super(Test, cls).tearDownClass()
def callxmrnodewallet(self, node_id, method, params=None):
return callrpc_xmr(XMR_BASE_WALLET_RPC_PORT + node_id, self.xmr_wallet_auth[node_id], method, params)
def wait_for_offer(self, swap_client, offer_id):
logging.info('wait_for_offer %s', offer_id.hex())
for i in range(20):
time.sleep(1)
offers = swap_client.listOffers()
for offer in offers:
if offer.offer_id == offer_id:
return
raise ValueError('wait_for_offer timed out.')
def test_01_part_xmr(self):
logging.info('---------- Test PART to XMR')
#swap_clients = self.swap_clients
swap_clients = self.swap_clients
js_0 = json.loads(urlopen('http://localhost:1800/json/wallets').read())
assert(make_int(js_0[str(int(Coins.XMR))]['balance'], scale=12) > 0)
assert(make_int(js_0[str(int(Coins.XMR))]['unconfirmed'], scale=12) > 0)
#offer_id = swap_clients[0].postOffer(Coins.PART, Coins.XMR, 100 * COIN, 0.5 * COIN, 100 * COIN, SwapTypes.SELLER_FIRST)
offer_id = swap_clients[0].postOffer(Coins.PART, Coins.XMR, 100 * COIN, 10 * XMR_COIN, 100 * COIN, SwapTypes.XMR_SWAP)
self.wait_for_offer(swap_clients[1], offer_id)
offers = swap_clients[1].listOffers()
assert(len(offers) == 1)
for offer in offers:
print('offer', offer)
if __name__ == '__main__':

Loading…
Cancel
Save