Fix contract_count not inserted in db
This commit is contained in:
parent
5d84d54e6f
commit
acae8b4de3
@ -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)
|
||||
|
51
basicswap/contrib/rpcauth.py
Executable file
51
basicswap/contrib/rpcauth.py
Executable file
@ -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()
|
||||
|
||||
|
12
basicswap/interface_nmc.py
Normal file
12
basicswap/interface_nmc.py
Normal file
@ -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,28 +295,29 @@ _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),
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
@ -274,37 +330,164 @@ _BIDACCEPTMESSAGE = _descriptor.Descriptor(
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=563,
|
||||
serialized_end=649,
|
||||
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, 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,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
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()
|
||||
|
1
setup.py
1
setup.py
@ -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,45 +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)
|
||||
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('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')
|
||||
|
||||
with open(filePath, 'w+') as fp:
|
||||
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 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)
|
||||
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')
|
||||
@ -83,88 +140,100 @@ def prepareOtherDir(datadir, nodeId, conf_file='litecoin.conf'):
|
||||
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('fallbackfee=0.01\n')
|
||||
fp.write('acceptnonstdtxn=0\n')
|
||||
fp.write('txindex=1\n')
|
||||
|
||||
|
||||
def prepareDir(datadir, nodeId, network_key, network_pubkey):
|
||||
node_dir = os.path.join(datadir, str(nodeId))
|
||||
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:
|
||||
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('zmqpubsmsg=tcp://127.0.0.1:' + str(BASE_ZMQ_PORT + nodeId) + '\n')
|
||||
# minstakeinterval=5 # Using walletsettings stakelimit instead
|
||||
|
||||
fp.write('acceptnonstdtxn=0\n')
|
||||
fp.write('minstakeinterval=5\n')
|
||||
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))
|
||||
|
||||
if nodeId < 2:
|
||||
fp.write('spentindex=1\n')
|
||||
fp.write('txindex=1\n')
|
||||
|
||||
basicswap_dir = os.path.join(datadir, str(nodeId), 'basicswap')
|
||||
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))
|
||||
|
||||
return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
|
||||
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):
|
||||
return callrpc_cli(cfg.BITCOIN_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)), 'regtest', cmd, cfg.BITCOIN_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 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
|
||||
cls.btc_addr = None
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
cls.update_thread = threading.Thread(target=run_loop, args=(cls,))
|
||||
cls.update_thread.start()
|
||||
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
|
||||
|
||||
#offer_id = swap_clients[0].postOffer(Coins.PART, Coins.XMR, 100 * COIN, 0.5 * COIN, 100 * COIN, SwapTypes.SELLER_FIRST)
|
||||
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, 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…
Reference in New Issue
Block a user