From f0014bb8845e5c6bc312e406decb4a08e1dcafaf Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Thu, 23 Feb 2023 16:19:15 +0300 Subject: [PATCH 01/13] sync pytests with research-archive --- qa/pytest_komodo/__init__.py | 0 qa/pytest_komodo/basic/pytest_util.py | 268 --------- qa/pytest_komodo/basic/test_blocks.py | 55 +- .../basic/test_control_address.py | 3 +- qa/pytest_komodo/basic/test_network_mining.py | 4 +- .../basic/test_rawtransactions.py | 2 +- qa/pytest_komodo/basic/test_shielded.py | 4 +- qa/pytest_komodo/basic/test_utils.py | 4 +- qa/pytest_komodo/basic/test_wallet.py | 4 +- qa/pytest_komodo/cc_modules/test_channels.py | 531 +++++++++------- qa/pytest_komodo/cc_modules/test_dice.py | 435 ++++++++------ qa/pytest_komodo/cc_modules/test_faucet.py | 220 ++++--- qa/pytest_komodo/cc_modules/test_heir.py | 466 ++++++++++----- qa/pytest_komodo/cc_modules/test_oracles.py | 565 +++++++++--------- qa/pytest_komodo/cc_modules/test_rewards.py | 316 ++++++---- qa/pytest_komodo/cc_modules/test_token.py | 540 +++++++++-------- qa/pytest_komodo/cc_modules/test_tokenv2.py | 314 ++++++++++ .../cc_modules/test_unspentccundex.py | 142 +++++ qa/pytest_komodo/chainconfig.json | 7 +- qa/pytest_komodo/chainstart.py | 2 +- qa/pytest_komodo/ci_cleanup.sh | 5 - qa/pytest_komodo/ci_set_dex.sh | 14 +- qa/pytest_komodo/ci_setup.sh | 8 +- qa/pytest_komodo/conftest.py | 39 +- qa/pytest_komodo/lib/__init__.py | 0 qa/pytest_komodo/lib/pytest_util.py | 565 ++++++++++++++++++ qa/pytest_komodo/{cc_modules => lib}/util.py | 5 +- qa/pytest_komodo/modules/test_dexp2p.py | 2 +- qa/pytest_komodo/modules/test_dexp2p_e2e.py | 2 +- qa/pytest_komodo/nodesconfig.json | 12 +- qa/pytest_komodo/start_ci.bat | 8 +- qa/pytest_komodo/start_set_dex.bat | 14 +- qa/pytest_komodo/sync/pytest_util.py | 52 -- qa/pytest_komodo/sync/test_sync.py | 2 +- 34 files changed, 2908 insertions(+), 1702 deletions(-) create mode 100644 qa/pytest_komodo/__init__.py delete mode 100644 qa/pytest_komodo/basic/pytest_util.py create mode 100644 qa/pytest_komodo/cc_modules/test_tokenv2.py create mode 100644 qa/pytest_komodo/cc_modules/test_unspentccundex.py delete mode 100755 qa/pytest_komodo/ci_cleanup.sh create mode 100644 qa/pytest_komodo/lib/__init__.py create mode 100644 qa/pytest_komodo/lib/pytest_util.py rename qa/pytest_komodo/{cc_modules => lib}/util.py (95%) delete mode 100644 qa/pytest_komodo/sync/pytest_util.py diff --git a/qa/pytest_komodo/__init__.py b/qa/pytest_komodo/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/qa/pytest_komodo/basic/pytest_util.py b/qa/pytest_komodo/basic/pytest_util.py deleted file mode 100644 index ab1e395fa26..00000000000 --- a/qa/pytest_komodo/basic/pytest_util.py +++ /dev/null @@ -1,268 +0,0 @@ -import time -import jsonschema -import os -import random -import string -import hashlib -import re -try: - from slickrpc import Proxy - from slickrpc.exc import RpcException as RPCError - from pycurl import error as HttpError -except ImportError: # fallback to bitcoinrpc - from bitcoinrpc.authproxy import AuthServiceProxy as Proxy - from bitcoinrpc.authproxy import JSONRPCException as RPCError - from http.client import HTTPException as HttpError - - -def create_proxy(node_params_dictionary): - try: - proxy = Proxy("http://%s:%s@%s:%d" % (node_params_dictionary.get('rpc_user'), - node_params_dictionary.get('rpc_password'), - node_params_dictionary.get('rpc_ip'), - node_params_dictionary.get('rpc_port')), timeout=120) - except Exception as e: - raise Exception("Connection error! Probably no daemon on selected port. Error: ", e) - return proxy - - -def validate_proxy(env_params_dictionary, proxy, node=0): - attempts = 0 - while True: # base connection check - try: - getinfo_output = proxy.getinfo() - print(getinfo_output) - break - except Exception as e: - print("Coennction failed, error: ", e, "\nRetrying") - attempts += 1 - time.sleep(10) - if attempts > 15: - raise ChildProcessError("Node ", node, " does not respond") - print("IMPORTING PRIVKEYS") - res = proxy.importprivkey(env_params_dictionary.get('test_wif')[node], '', True) - print(res) - assert proxy.validateaddress(env_params_dictionary.get('test_address')[node])['ismine'] - try: - pubkey = env_params_dictionary.get('test_pubkey')[node] - assert proxy.getinfo()['pubkey'] == pubkey - except (KeyError, IndexError): - print("\nNo -pubkey= runtime parameter specified") - assert proxy.verifychain() - time.sleep(15) - print("\nBalance: " + str(proxy.getbalance())) - print("Each node should have at least 777 coins to perform CC tests\n") - - -def enable_mining(proxy): - cores = os.cpu_count() - if cores > 2: - threads_count = cores - 2 - else: - threads_count = 1 - tries = 0 - while True: - try: - proxy.setgenerate(True, threads_count) - break - except (RPCError, HttpError) as e: - print(e, " Waiting chain startup\n") - time.sleep(10) - tries += 1 - if tries > 30: - raise ChildProcessError("Node did not start correctly, aborting\n") - - -def mine_and_waitconfirms(txid, proxy, confs_req=2): # should be used after tx is send - # we need the tx above to be confirmed in the next block - attempts = 0 - while True: - try: - confirmations_amount = proxy.getrawtransaction(txid, 1)['confirmations'] - if confirmations_amount < confs_req: - print("\ntx is not confirmed yet! Let's wait a little more") - time.sleep(5) - else: - print("\ntx confirmed") - return True - except KeyError as e: - print("\ntx is in mempool still probably, let's wait a little bit more\nError: ", e) - time.sleep(5) - attempts += 1 - if attempts < 100: - pass - else: - print("\nwaited too long - probably tx stuck by some reason") - return False - - -def validate_transaction(proxy, txid, conf_req): - try: - isinstance(proxy, Proxy) - except Exception as e: - raise TypeError("Not a Proxy object, error: " + str(e)) - conf = 0 - while conf < conf_req: - print("\nWaiting confirmations...") - resp = proxy.gettransaction(txid) - conf = resp.get('confirmations') - time.sleep(2) - - -def validate_template(blocktemplate, schema=''): # BIP 0022 - blockschema = { - 'type': 'object', - 'required': ['bits', 'curtime', 'height', 'previousblockhash', 'version', 'coinbasetxn'], - 'properties': { - 'capabilities': {'type': 'array', - 'items': {'type': 'string'}}, - 'version': {'type': ['integer', 'number']}, - 'previousblockhash': {'type': 'string'}, - 'finalsaplingroothash': {'type': 'string'}, - 'transactions': {'type': 'array', - 'items': {'type': 'object'}}, - 'coinbasetxn': {'type': 'object', - 'required': ['data', 'hash', 'depends', 'fee', 'required', 'sigops'], - 'properties': { - 'data': {'type': 'string'}, - 'hash': {'type': 'string'}, - 'depends': {'type': 'array'}, - 'fee': {'type': ['integer', 'number']}, - 'sigops': {'type': ['integer', 'number']}, - 'coinbasevalue': {'type': ['integer', 'number']}, - 'required': {'type': 'boolean'} - } - }, - 'longpollid': {'type': 'string'}, - 'target': {'type': 'string'}, - 'mintime': {'type': ['integer', 'number']}, - 'mutable': {'type': 'array', - 'items': {'type': 'string'}}, - 'noncerange': {'type': 'string'}, - 'sigoplimit': {'type': ['integer', 'number']}, - 'sizelimit': {'type': ['integer', 'number']}, - 'curtime': {'type': ['integer', 'number']}, - 'bits': {'type': 'string'}, - 'height': {'type': ['integer', 'number']} - } - } - if not schema: - schema = blockschema - jsonschema.validate(instance=blocktemplate, schema=schema) - - -def check_synced(*proxies): - for proxy in proxies: - tries = 0 - while True: - check = proxy.getinfo().get('synced') - proxy.ping() - if check: - print("Synced\n") - break - else: - print("Waiting for sync\nAttempt: ", tries + 1, "\n") - time.sleep(10) - tries += 1 - if tries > 120: # up to 20 minutes - return False - return True - - -def randomstring(length): - chars = string.ascii_letters - return ''.join(random.choice(chars) for i in range(length)) - - -def in_99_range(compare, base): - if compare >= 0.99*base: - return True - else: - return False - - -def compare_rough(base, comp, limit=30): - if base >= comp - limit: - return True - else: - return False - - -def collect_orderids(rpc_response, dict_key): # see dexp2p tests in modules - orderids = [] - for item in rpc_response.get(dict_key): - orderids.append(str(item.get('id'))) - return orderids - - -def randomhex(): # returns 64 chars long pubkey-like hex string - chars = string.hexdigits - return (''.join(random.choice(chars) for i in range(64))).lower() - - -def write_file(filename): # creates text file - lines = 10 - content = '' - for x in range(lines): - content += randomhex() + '\n' - with open(filename, 'w') as f: - f.write(str('filename\n')) - f.write(content) - return True - - -def write_empty_file(filename: str, size: int): # creates empty file slightly bigger than size in mb - if os.path.isfile(filename): - os.remove(filename) - with open(filename, 'wb') as f: - f.seek((size * 1024 * 1025) - 1) - f.write(b'\0') - - -def get_size(file): - if os.path.isfile(file): - return os.path.getsize(file) - else: - raise FileNotFoundError - - -def get_filehash(file): - if os.path.isfile(file): - with open(file, "rb") as f: - bytez = f.read() # read entire file as bytes - fhash = hashlib.sha256(bytez).hexdigest() - return str(fhash) - else: - raise FileNotFoundError - - -def validate_tx_pattern(txid): - if not isinstance(txid, str): - return False - pattern = re.compile('[0-9a-f]{64}') - if pattern.match(txid): - return True - else: - return False - - -def validate_raddr_pattern(addr): - if not isinstance(addr, str): - return False - address_pattern = re.compile(r"R[a-zA-Z0-9]{33}\Z") - if address_pattern.match(addr): - return True - else: - return False - - -def wait_blocks(rpc_connection, blocks_to_wait): - init_height = int(rpc_connection.getinfo()["blocks"]) - while True: - current_height = int(rpc_connection.getinfo()["blocks"]) - height_difference = current_height - init_height - if height_difference < blocks_to_wait: - print("Waiting for more blocks") - time.sleep(5) - else: - return True \ No newline at end of file diff --git a/qa/pytest_komodo/basic/test_blocks.py b/qa/pytest_komodo/basic/test_blocks.py index 83d4e4d026b..7bbe094c045 100644 --- a/qa/pytest_komodo/basic/test_blocks.py +++ b/qa/pytest_komodo/basic/test_blocks.py @@ -1,11 +1,10 @@ #!/usr/bin/env python3 # Copyright (c) 2019 SuperNET developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest -from pytest_util import validate_transaction -from pytest_util import validate_template +from lib.pytest_util import validate_transaction, validate_template from decimal import * @@ -309,6 +308,56 @@ def test_gettxoutsetinfo(self, test_params): res = rpc.gettxoutsetinfo() validate_template(res, schema) + def test_kvupdate(self, test_params): + test_values = { + 'v_key': 'valid_key', + 'value': 'test+value', + 'days': '2', + 'pass': 'secret', + 'n_key': 'invalid_key', + 'keylen': 9 + } + rpc = test_params.get('node1').get('rpc') + res = rpc.kvupdate(test_values['v_key'], test_values['value'], test_values['days'], test_values['pass']) + assert res.get('key') == test_values['v_key'] + assert res.get('keylen') == test_values['keylen'] + assert res.get('value') == test_values['value'] + + def test_getrawmempool(self, test_params): + test_values = { + 'key': 'mempool_key', + 'value': 'key_value', + 'days': '1', + 'pass': 'secret' + } # to get info into mempool, we need to create tx, kvupdate call creates one for us + rpc = test_params.get('node1').get('rpc') + res = rpc.kvupdate(test_values['key'], test_values['value'], test_values['days'], test_values['pass']) + txid = res.get('txid') + kvheight = res.get('height') + res = rpc.getrawmempool() + assert txid in res + res = rpc.getrawmempool(False) # False is default value, res should be same as in call above + assert txid in res + res = rpc.getrawmempool(True) + assert res.get(txid).get('height') == kvheight + + def test_kvsearch(self, test_params): + test_values = { + 'key': 'search_key', + 'value': 'search_value', + 'days': '1', + 'pass': 'secret' + } + rpc = test_params.get('node1').get('rpc') + res = rpc.kvupdate(test_values['key'], test_values['value'], test_values['days'], test_values['pass']) + txid = res.get('txid') + keylen = res.get('keylen') + validate_transaction(rpc, txid, 1) # wait for block + res = rpc.kvsearch(test_values['key']) + assert res.get('key') == test_values['key'] + assert res.get('keylen') == keylen + assert res.get('value') == test_values['value'] + def test_notaries(self, test_params): rpc = test_params.get('node1').get('rpc') res = rpc.notaries('1') diff --git a/qa/pytest_komodo/basic/test_control_address.py b/qa/pytest_komodo/basic/test_control_address.py index df0ecaa8828..1646c33be47 100644 --- a/qa/pytest_komodo/basic/test_control_address.py +++ b/qa/pytest_komodo/basic/test_control_address.py @@ -1,10 +1,9 @@ #!/usr/bin/env python3 # Copyright (c) 2019 SuperNET developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest -import json @pytest.mark.usefixtures("proxy_connection") diff --git a/qa/pytest_komodo/basic/test_network_mining.py b/qa/pytest_komodo/basic/test_network_mining.py index 8a100f07165..329cf2770a5 100644 --- a/qa/pytest_komodo/basic/test_network_mining.py +++ b/qa/pytest_komodo/basic/test_network_mining.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 # Copyright (c) 2019 SuperNET developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest import time from decimal import * -from pytest_util import validate_template +from lib.pytest_util import validate_template @pytest.mark.usefixtures("proxy_connection") diff --git a/qa/pytest_komodo/basic/test_rawtransactions.py b/qa/pytest_komodo/basic/test_rawtransactions.py index e5d11ffc63f..322717bfc28 100644 --- a/qa/pytest_komodo/basic/test_rawtransactions.py +++ b/qa/pytest_komodo/basic/test_rawtransactions.py @@ -5,7 +5,7 @@ import pytest from decimal import * -from pytest_util import validate_template, mine_and_waitconfirms +from lib.pytest_util import validate_template, mine_and_waitconfirms @pytest.mark.usefixtures("proxy_connection") diff --git a/qa/pytest_komodo/basic/test_shielded.py b/qa/pytest_komodo/basic/test_shielded.py index c336cf4ebdd..0847d2ef55d 100644 --- a/qa/pytest_komodo/basic/test_shielded.py +++ b/qa/pytest_komodo/basic/test_shielded.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 # Copyright (c) 2019 SuperNET developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest import time from decimal import * -from pytest_util import validate_template, check_synced, mine_and_waitconfirms +from lib.pytest_util import validate_template, check_synced, mine_and_waitconfirms @pytest.mark.usefixtures("proxy_connection") diff --git a/qa/pytest_komodo/basic/test_utils.py b/qa/pytest_komodo/basic/test_utils.py index da95a296773..834b283d603 100644 --- a/qa/pytest_komodo/basic/test_utils.py +++ b/qa/pytest_komodo/basic/test_utils.py @@ -1,10 +1,10 @@ #!/usr/bin/env python3 # Copyright (c) 2019 SuperNET developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest -from pytest_util import validate_template +from lib.pytest_util import validate_template @pytest.mark.usefixtures("proxy_connection") diff --git a/qa/pytest_komodo/basic/test_wallet.py b/qa/pytest_komodo/basic/test_wallet.py index 87acd29bd15..eba8e4fd98d 100644 --- a/qa/pytest_komodo/basic/test_wallet.py +++ b/qa/pytest_komodo/basic/test_wallet.py @@ -1,11 +1,11 @@ #!/usr/bin/env python3 # Copyright (c) 2019 SuperNET developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest from decimal import * -from pytest_util import validate_template, mine_and_waitconfirms +from lib.pytest_util import validate_template, mine_and_waitconfirms @pytest.mark.usefixtures("proxy_connection") diff --git a/qa/pytest_komodo/cc_modules/test_channels.py b/qa/pytest_komodo/cc_modules/test_channels.py index fd72b2139f0..b071090952c 100644 --- a/qa/pytest_komodo/cc_modules/test_channels.py +++ b/qa/pytest_komodo/cc_modules/test_channels.py @@ -1,229 +1,312 @@ #!/usr/bin/env python3 -# Copyright (c) 2019 SuperNET developers +# Copyright (c) 2021 SuperNET developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest import time - -from util import assert_success, assert_error, check_if_mined, send_and_mine,\ - rpc_connect, wait_some_blocks, generate_random_string, komodo_teardown - - -@pytest.mark.usefixtures("proxy_connection") -def test_channels(test_params): - - # test params inits - rpc = test_params.get('node1').get('rpc') - rpc1 = test_params.get('node2').get('rpc') - - pubkey = test_params.get('node1').get('pubkey') - pubkey1 = test_params.get('node2').get('pubkey') - - is_fresh_chain = test_params.get("is_fresh_chain") - - """!!! for testing needed test daemon which built with custom flag - export CONFIGURE_FLAGS='CPPFLAGS=-DTESTMODE' - since in usual mode 101 confirmations are needed for payment/refund - """ - - # checking channelsaddress call - - result = rpc.channelsaddress(pubkey) - assert_success(result) - # test that additional CCaddress key is returned - - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - # getting empty channels list - - result = rpc.channelslist() - assert result["result"] == "success" - assert result["name"] == "Channels List" - if is_fresh_chain: - assert len(result) == 2 - - # 10 payments, 100000 sat denomination channel opening with second node pubkey - new_channel_hex = rpc.channelsopen(pubkey1, "10", "100000") - assert_success(new_channel_hex) - channel_txid = send_and_mine(new_channel_hex["hex"], rpc) - assert channel_txid, "got channel txid" - - # checking if our new channel in common channels list - if is_fresh_chain: - result = rpc.channelslist() - assert len(result) == 3 - - # checking info about channel directly - result = rpc.channelsinfo(channel_txid) - assert_success(result) - assert result["Transactions"][0]["Open"] == channel_txid - - # open transaction should be confirmed at least twice - wait_some_blocks(rpc, 3) - - # trying to make wrong denomination channel payment - result = rpc.channelspayment(channel_txid, "199000") - assert_error(result) - - # trying to make 0 channel payment - result = rpc.channelspayment(channel_txid, "0") - assert_error(result) - - # trying to make negative channel payment - result = rpc.channelspayment(channel_txid, "-1") - assert_error(result) - - # valid channel payment - result = rpc.channelspayment(channel_txid, "100000") - assert_success(result) - payment_tx_id = send_and_mine(result["hex"], rpc) - assert payment_tx_id, "got txid" - - # now in channelinfo payment information should appear - result = rpc.channelsinfo(channel_txid) - assert result["Transactions"][1]["Payment"] == payment_tx_id - - # number of payments should be equal 1 (one denomination used) - result = rpc.channelsinfo(channel_txid)["Transactions"][1]["Number of payments"] - assert result == 1 - # payments left param should reduce 1 and be equal 9 now ( 10 - 1 = 9 ) - result = rpc.channelsinfo(channel_txid)["Transactions"][1]["Payments left"] - assert result == 9 - - # lets try payment with x2 amount to ensure that counters works correct - result = rpc.channelspayment(channel_txid, "200000") - assert_success(result) - payment_tx_id = send_and_mine(result["hex"], rpc) - assert payment_tx_id, "got txid" - - result = rpc.channelsinfo(channel_txid) - assert result["Transactions"][2]["Payment"] == payment_tx_id - - result = rpc.channelsinfo(channel_txid)["Transactions"][2]["Number of payments"] - assert result == 2 - - result = rpc.channelsinfo(channel_txid)["Transactions"][2]["Payments left"] - assert result == 7 - - # check if payment value really transferred - raw_transaction = rpc.getrawtransaction(payment_tx_id, 1) - - result = raw_transaction["vout"][3]["valueSat"] - assert result == 200000 - - result = rpc1.validateaddress(raw_transaction["vout"][3]["scriptPubKey"]["addresses"][0])["ismine"] - assert result - - # have to check that second node have coins to cover txfee at least - rpc.sendtoaddress(rpc1.getnewaddress(), 1) - time.sleep(10) # to ensure transactions are in different blocks - rpc.sendtoaddress(rpc1.getnewaddress(), 1) - wait_some_blocks(rpc, 2) - result = rpc1.getbalance() - assert result > 0.1 - - # trying to initiate channels payment from node B without any secret - # TODO: have to add RPC validation - payment_hex = rpc1.channelspayment(channel_txid, "100000") - try: - result = rpc1.sendrawtransaction(payment_hex["hex"]) - except Exception as e: - pass - - # trying to initiate channels payment from node B with secret from previous payment - result = rpc1.channelspayment(channel_txid, "100000", rpc1.channelsinfo(channel_txid)["Transactions"][1]["Secret"]) - # result = rpc1.sendrawtransaction(payment_hex["hex"]) - assert_error(result) - - # executing channel close - result = rpc.channelsclose(channel_txid) - # TODO: by some reason channels close just returning hex instead of result and hex json - channel_close_txid = send_and_mine(result, rpc) - assert channel_close_txid, "got txid" - - wait_some_blocks(rpc, 2) - - # now in channelinfo closed flag should appear - result = rpc.channelsinfo(channel_txid) - assert result["Transactions"][3]["Close"] == channel_close_txid - - # executing channel refund - result = rpc.channelsrefund(channel_txid, channel_close_txid) - # TODO: by some reason channels refund just returning hex instead of result and hex json - refund_txid = send_and_mine(result, rpc) - assert refund_txid, "got txid" - - # checking if it refunded to opener address - raw_transaction = rpc.getrawtransaction(refund_txid, 1) - - result = raw_transaction["vout"][2]["valueSat"] - assert result == 700000 - - result = rpc.validateaddress(raw_transaction["vout"][2]["scriptPubKey"]["addresses"][0])["ismine"] - assert result - - # creating and draining channel (10 payment by 100000 satoshies in total to fit full capacity) - new_channel_hex1 = rpc.channelsopen(pubkey1, "10", "100000") - assert_success(new_channel_hex1) - channel1_txid = send_and_mine(new_channel_hex1["hex"], rpc) - assert channel1_txid, "got channel txid" - - # need to have 2+ confirmations in the test mode - wait_some_blocks(rpc, 2) - - # TODO: maybe it's possible to send in single block to not wait 10 blocks? - for i in range(10): - result = rpc.channelspayment(channel1_txid, "100000") - assert_success(result) - payment_tx_id = send_and_mine(result["hex"], rpc) - assert payment_tx_id, "got txid" - - # last payment should indicate that 0 payments left - result = rpc.channelsinfo(channel1_txid)["Transactions"][10]["Payments left"] - assert result == 0 - - # no more payments possible - result = rpc.channelspayment(channel1_txid, "100000") - assert_error(result) - -# TODO: fixme -# -# # creating new channel to test the case when node B initiate payment when node A revealed secret in offline -# # 10 payments, 100000 sat denomination channel opening with second node pubkey -# new_channel_hex2 = rpc.channelsopen(pubkey1, "10", "100000") -# assert_success(new_channel_hex) -# channel2_txid = send_and_mine(new_channel_hex2["hex"], rpc) -# assert channel2_txid, "got channel txid" -# -# wait_some_blocks(rpc, 2) -# -# # disconnecting first node from network -# rpc.setban("127.0.0.0/24", "add") -# assert rpc.getinfo()["connections"] == 0 -# assert rpc1.getinfo()["connections"] == 0 -# -# # sending one payment to mempool to reveal the secret but not mine it -# payment_hex = rpc.channelspayment(channel2_txid, "100000") -# result = rpc.sendrawtransaction(payment_hex["hex"]) -# assert result, "got payment txid" -# -# secret = rpc.channelsinfo(channel2_txid)["Transactions"][1]["Secret"] -# assert secret, "Secret revealed" -# -# # secret shouldn't be available for node B -# secret_not_revealed = None -# try: -# rpc1.channelsinfo(channel2_txid)["Transactions"][1]["Secret"] -# except Exception: -# secret_not_revealed -# assert secret_not_revealed -# -# # trying to initiate payment from second node with revealed secret -# assert rpc1.getinfo()["connections"] == 0 -# dc_payment_hex = rpc1.channelspayment(channel2_txid, "100000", secret) -# assert_success(dc_payment_hex) -# result = rpc1.sendrawtransaction(dc_payment_hex["hex"]) -# assert result, "got channelspayment transaction id" +from lib.pytest_util import validate_template, mine_and_waitconfirms, validate_raddr_pattern, validate_tx_pattern + + +@pytest.mark.usefixtures("proxy_connection", "test_params") +class TestChannelsCCBase: + + def test_channelsaddress(self, channel_instance): + channelsaddress_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'error': {'type': 'string'}, + 'ChannelsCCAddress': {'type': 'string'}, + 'ChannelsCCBalance': {'type': 'number'}, + 'ChannelsNormalAddress': {'type': 'string'}, + 'ChannelsNormalBalance': {'type': 'number'}, + 'ChannelsCC1of2Address': {'type': 'string'}, + 'ChannelsCC1of2TokensAddress': {'type': 'string'}, + 'PubkeyCCaddress(Channels)': {'type': 'string'}, + 'PubkeyCCbalance(Channels)': {'type': 'number'}, + 'myCCAddress(Channels)': {'type': 'string'}, + 'myCCbalance(Channels)': {'type': 'number'}, + 'myaddress': {'type': 'string'}, + 'mybalance': {'type': 'number'} + }, + 'required': ['result'] + } + + rpc1 = channel_instance.rpc[0] + pubkey2 = channel_instance.pubkey[1] + + res = rpc1.channelsaddress(pubkey2) + validate_template(res, channelsaddress_schema) + for key in res.keys(): + if key.find('ddress') > 0: + assert validate_raddr_pattern(res.get(key)) + + def test_channelsopen(self, channel_instance): + channelsopen_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'error': {'type': 'string'}, + 'hex': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc1 = channel_instance.rpc[0] + pubkey2 = channel_instance.pubkey[1] + channel_instance.new_channel(rpc1, pubkey2, '10', '100000', schema=channelsopen_schema) + + def test_channelslist(self, channel_instance): + channelsinfo_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'error': {'type': 'string'}, + 'name': {'type': 'string'}, + '[0-9a-f]{64}': {'type': 'string'} # 'txid': "channels info and payments info" + }, + 'required': ['result'] + } + + rpc1 = channel_instance.rpc[0] + channel_instance.channelslist_get(rpc1, channelsinfo_schema) + + def test_channelsinfo(self, channel_instance): + channelsinfo_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'error': {'type': 'string'}, + "Channel CC address": {'type': 'string'}, + "Destination address": {'type': 'string'}, + "Number of payments": {'type': 'integer'}, + "Denomination (satoshi)": {'type': 'string'}, + "Amount (satoshi)": {'type': 'string'}, + "Token id": {'type': 'string'}, + 'Transactions': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'Open': {'type': 'string'}, + 'Payment': {'type': 'string'}, + "Number of payments": {'type': 'integer'}, + 'Amount': {'type': 'integer'}, + 'Destination': {'type': 'string'}, + 'Secret': {'type': 'string'}, + "Payments left": {'type': 'integer'} + } + } + } + }, + 'required': ['result'] + } + + rpc1 = channel_instance.rpc[0] + pubkey2 = channel_instance.pubkey[1] + if not channel_instance.base_channel: + channel_instance.new_channel(rpc1, pubkey2) + res = rpc1.channelsinfo(channel_instance.base_channel.get('open_txid')) + validate_template(res, channelsinfo_schema) + + def test_channelspayment(self, channel_instance): + channelspayment_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'error': {'type': 'string'}, + 'hex': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc1 = channel_instance.rpc[0] + pubkey2 = channel_instance.pubkey[1] + if not channel_instance.base_channel: + channel_instance.new_channel(rpc1, pubkey2) + minpayment = '100000' + else: + minpayment = rpc1.channelsinfo(channel_instance.base_channel.get('open_txid')).get("Denomination (satoshi)") + res = rpc1.channelspayment(channel_instance.base_channel.get('open_txid'), minpayment) + validate_template(res, channelspayment_schema) + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + + def test_channels_closenrefund(self, channel_instance): + channels_refund_close_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'error': {'type': 'string'}, + 'hex': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc1 = channel_instance.rpc[0] + pubkey2 = channel_instance.pubkey[1] + minpayment = '100000' + newchannel = channel_instance.new_channel(rpc1, pubkey2, '2', minpayment) + + # send 1 payment and close channel + res = rpc1.channelspayment(newchannel.get('open_txid'), minpayment) + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + res = rpc1.channelsclose(newchannel.get('open_txid')) + validate_template(res, channels_refund_close_schema) + close_txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(close_txid, rpc1) + + # execute refund + res = rpc1.channelsrefund(newchannel.get('open_txid'), close_txid) + validate_template(res, channels_refund_close_schema) + refund_txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(refund_txid, rpc1) + + +@pytest.mark.usefixtures("proxy_connection", "test_params") +class TestChannelsCC: + def test_channels_flow(self, channel_instance): + rpc1 = channel_instance.rpc[0] + rpc2 = channel_instance.rpc[1] + pubkey2 = channel_instance.pubkey[1] + addr1 = channel_instance.address[0] + channel = channel_instance.new_channel(rpc1, pubkey2) + + # trying to make wrong denomination channel payment + res = rpc1.channelspayment(channel.get('open_txid'), '199000') + assert res.get('result') == 'error' + + # trying to make 0 channel payment + res = rpc1.channelspayment(channel.get('open_txid'), '0') + assert res.get('result') == 'error' + + # trying to make negative channel payment + res = rpc1.channelspayment(channel.get('open_txid'), '-100000') + assert res.get('result') == 'error' + + # lets try payment with x2 amount to ensure that counters works correct + res = rpc1.channelspayment(channel.get('open_txid'), '200000') + assert res.get('result') == 'success' + payment_tx_id = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(payment_tx_id, rpc1) + assert isinstance(payment_tx_id, str) + res = rpc1.channelsinfo(channel.get('open_txid')) + assert res['Transactions'][-1]['Payment'] == payment_tx_id + assert res['Transactions'][-1]["Number of payments"] == 2 + assert res['Transactions'][-1]["Payments left"] == 8 # 10 initial - 2 + + # check if payment value really transferred + raw_transaction = rpc1.getrawtransaction(payment_tx_id, 1) + res = raw_transaction['vout'][3]['valueSat'] + assert res == 200000 + res = rpc2.validateaddress(raw_transaction['vout'][3]['scriptPubKey']['addresses'][0])['ismine'] + assert res + + # trying to initiate channels payment from node B without any secret + res = rpc2.channelspayment(channel.get('open_txid'), "100000") + assert res.get('result') == 'error' + assert "invalid secret" in res.get('error') + + # trying to initiate channels payment from node B with secret from previous payment + secret = rpc2.channelsinfo(channel.get('open_txid'))['Transactions'][-1]['Secret'] + res = rpc2.channelspayment(channel.get('open_txid'), "100000", secret) + assert res.get('result') == 'error' + assert "invalid secret" in res.get('error') + + # executing channel close + res = rpc1.channelsclose(channel.get('open_txid')) + assert res.get('result') == 'success' + close_txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(close_txid, rpc1) + + # now in channelinfo closed flag should appear + res = rpc1.channelsinfo(channel.get('open_txid')) + assert res['Transactions'][-1]['Close'] == close_txid + + # executing channel refund + res = rpc1.channelsrefund(channel.get('open_txid'), close_txid) + assert res.get('result') == 'success' + refund_txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(refund_txid, rpc1) + + # checking if it refunded to opener address + raw = rpc1.getrawtransaction(refund_txid, 1) + res = raw['vout'] + values = [] + for vout in res: # find all txs to node1 address + try: + if vout.get('scriptPubKey').get('addresses')[0] == addr1 \ + and "OP_CHECKSIG" in vout.get('scriptPubKey').get('asm'): + values.append(vout.get('valueSat')) + except TypeError: # to prevent fails on OP_RETURN // nulldata vout + pass + assert 800000 in values # 10 - 2 payments, worth of 100000 satoshi each + + def test_channel_drain(self, channel_instance): + rpc1 = channel_instance.rpc[0] + pubkey2 = channel_instance.pubkey[1] + payments = '3' + pay_amount = '100000' + channel = channel_instance.new_channel(rpc1, pubkey2, payments, pay_amount) + + # draining channel (3 payment by 100000 satoshies in total to fit full capacity) + for i in range(3): + res = rpc1.channelspayment(channel.get('open_txid'), '100000') + assert res.get('result') == 'success' + payment_tx = rpc1.sendrawtransaction(res.get("hex")) + mine_and_waitconfirms(payment_tx, rpc1) + + # last payment should indicate that 0 payments left + res = rpc1.channelsinfo(channel.get('open_txid'))['Transactions'][-1]["Payments left"] + assert res == 0 + + # no more payments possible + res = rpc1.channelspayment(channel.get('open_txid'), '100000') + assert res.get('result') == 'error' + assert "error adding CC inputs" in res.get('error') + + def test_secret_reveal(self, channel_instance): + # creating new channel to test the case when node B initiate payment when node A revealed secret in offline + # 10 payments, 100000 sat denomination channel opening with second node pubkey + rpc1 = channel_instance.rpc[0] + rpc2 = channel_instance.rpc[1] + pubkey2 = channel_instance.pubkey[1] + channel = channel_instance.new_channel(rpc1, pubkey2) + + # disconnecting first node from network + rpc1.setban("127.0.0.0/24", 'add') + rpc2.setban("127.0.0.0/24", 'add') + # timewait for bans to take place + timeout = 40 + t_iter = 0 + while rpc1.getinfo()['connections'] != 0 or rpc2.getinfo()['connections'] != 0: + time.sleep(1) + t_iter += 1 + if t_iter >= timeout: + raise TimeoutError("Setban timeout: ", str(t_iter), "s") + + # sending one payment to mempool to reveal the secret but not mine it + payment_hex = rpc1.channelspayment(channel.get('open_txid'), '100000') + res = rpc1.sendrawtransaction(payment_hex['hex']) + assert isinstance(res, str) + + secret = rpc1.channelsinfo(channel.get('open_txid'))['Transactions'][1]['Secret'] + assert isinstance(res, str) + + # secret shouldn't be available for node B + try: + check = rpc2.channelsinfo(channel.get('open_txid'))['Transactions'][1]['Secret'] + except IndexError as e: + print(e) + check = None + assert not check + + # trying to initiate payment from second node with revealed secret + assert rpc1.getinfo()['connections'] == 0 + dc_payment_hex = rpc2.channelspayment(channel.get('open_txid'), '100000', secret) + res = rpc2.sendrawtransaction(dc_payment_hex['hex']) + assert isinstance(res, str) + rpc1.clearbanned() + rpc2.clearbanned() diff --git a/qa/pytest_komodo/cc_modules/test_dice.py b/qa/pytest_komodo/cc_modules/test_dice.py index d031bee33ea..14a7bf51590 100644 --- a/qa/pytest_komodo/cc_modules/test_dice.py +++ b/qa/pytest_komodo/cc_modules/test_dice.py @@ -1,192 +1,251 @@ #!/usr/bin/env python3 -# Copyright (c) 2019 SuperNET developers +# Copyright (c) 2020 SuperNET developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest -import json - -from util import assert_success, assert_error, check_if_mined, send_and_mine,\ - rpc_connect, wait_some_blocks, generate_random_string, komodo_teardown - - -@pytest.mark.usefixtures("proxy_connection") -def test_dice(test_params): - - # test params inits - rpc = test_params.get('node1').get('rpc') - rpc1 = test_params.get('node2').get('rpc') - - pubkey = test_params.get('node1').get('pubkey') - pubkey1 = test_params.get('node2').get('pubkey') - - is_fresh_chain = test_params.get("is_fresh_chain") - - - # second node should have some balance to place bets - result = rpc1.getbalance() - assert result > 99 - - result = rpc.diceaddress() - assert result['result'] == 'success' - - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - result = rpc.diceaddress(pubkey) - for x in result.keys(): - print(x + ": " + str(result[x])) - assert result['result'] == 'success' - - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - # no dice created yet - if is_fresh_chain: - result = rpc.dicelist() - assert result == [] - - # set dice name for futher usage - dicename = generate_random_string(5) - - # creating dice plan with too long name (>8 chars) - result = rpc.dicefund("THISISTOOLONG", "10000", "10", "10000", "10", "5") - assert_error(result) - - # creating dice plan with < 100 funding - result = rpc.dicefund(dicename, "10", "1", "10000", "10", "5") - assert_error(result) - - # creating dice plan with 0 blocks timeout - result = rpc.dicefund(dicename, "10", "1", "10000", "10", "0") - assert_error(result) - - # creating dice plan - dicefundtx = rpc.dicefund(dicename, "1000", "1", "800", "10", "5") - diceid = send_and_mine(dicefundtx['hex'], rpc) - - # checking if it in plans list now - result = rpc.dicelist() - assert diceid in result - - # adding zero funds to plan - result = rpc.diceaddfunds(dicename, diceid, "0") - assert_error(result) - - # adding negative funds to plan - result = rpc.diceaddfunds(dicename, diceid, "-1") - assert_error(result) - - # adding funds to plan - addfundstx = rpc.diceaddfunds(dicename, diceid, "1100") - result = send_and_mine(addfundstx['hex'], rpc) - - # checking if funds added to plan - result = rpc.diceinfo(diceid) - assert result["funding"] == "2100.00000000" - - # not valid dice info checking - result = rpc.diceinfo("invalid") - assert_error(result) - - # placing 0 amount bet - result = rpc1.dicebet(dicename, diceid, "0", "2") - assert_error(result) - - # placing negative amount bet - result = rpc1.dicebet(dicename, diceid, "-1", "2") - assert_error(result) - - # placing bet more than maxbet - result = rpc1.dicebet(dicename, diceid, "900", "2") - assert_error(result) - - # placing bet with amount more than funding - result = rpc1.dicebet(dicename, diceid, "3000", "2") - assert_error(result) - - # placing bet with potential won more than funding - result = rpc1.dicebet(dicename, diceid, "750", "9") - assert_error(result) - - # placing 0 odds bet - result = rpc1.dicebet(dicename, diceid, "1", "0") - assert_error(result) - - # placing negative odds bet - result = rpc1.dicebet(dicename, diceid, "1", "-1") - assert_error(result) - - # placing bet with odds more than allowed - result = rpc1.dicebet(dicename, diceid, "1", "11") - assert_error(result) - - # placing bet with not correct dice name - result = rpc1.dicebet("nope", diceid, "100", "2") - assert_error(result) - - # placing bet with not correct dice id - result = rpc1.dicebet(dicename, pubkey, "100", "2") - assert_error(result) - - # TODO: fixme - # # have to make some entropy for the next test - # entropytx = 0 - # fundingsum = 1 - # while entropytx < 110: - # fundingsuminput = str(fundingsum) - # fundinghex = rpc.diceaddfunds(dicename, diceid, fundingsuminput) - # entropytx = entropytx + 1 - # fundingsum = fundingsum + 1 - # if entropytx < 109: - # result = rpc.sendrawtransaction(fundinghex['hex']) - # else: - # result = send_and_mine(fundinghex['hex'], rpc) - # - # wait_some_blocks(rpc, 2) - # - # # valid bet placing - # placebet = rpc1.dicebet(dicename, diceid, "101", "3") - # print(placebet) - # betid = send_and_mine(placebet["hex"], rpc1) - # assert result, "bet placed" - # - # # check bet status - # result = rpc1.dicestatus(dicename, diceid, betid) - # assert_success(result) - # - # # note initial dice funding state at this point. - # # TODO: track player balance somehow (hard to do because of mining and fees) - # diceinfo = rpc.diceinfo(diceid) - # funding = float(diceinfo['funding']) - # - # - # # placing same amount bets with amount 1 and odds 1:3, checking if balance changed correct - # losscounter = 0 - # wincounter = 0 - # betcounter = 0 - # - # while (betcounter < 10): - # placebet = rpc1.dicebet(dicename,diceid,"1","2") - # betid = self.send_and_mine(placebet["hex"], rpc1) - # time.sleep(3) - # self.sync_all() - # finish = rpc.dicefinish(dicename,diceid,betid) - # self.send_and_mine(finish["hex"], rpc1) - # self.sync_all() - # time.sleep(3) - # betresult = rpc1.dicestatus(dicename,diceid,betid) - # betcounter = betcounter + 1 - # if betresult["status"] == "loss": - # losscounter = losscounter + 1 - # elif betresult["status"] == "win": - # wincounter = wincounter + 1 - # else: - # pass - # - # # funding balance should increase if player loss, decrease if player won - # fundbalanceguess = funding + losscounter - wincounter * 2 - # fundinfoactual = rpc.diceinfo(diceid) - # assert_equal(round(fundbalanceguess),round(float(fundinfoactual['funding']))) +from lib.pytest_util import validate_template, mine_and_waitconfirms, randomstring,\ + randomhex, wait_blocks, validate_raddr_pattern, check_synced +from decimal import * + + +@pytest.mark.usefixtures("proxy_connection", "test_params") +class TestDiceCCBase: + + def test_diceaddress(self, dice_casino): + diceaddress_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'DiceCCAddress': {'type': 'string'}, + 'DiceCCBalance': {'type': 'number'}, + 'DiceNormalAddress': {'type': 'string'}, + 'DiceNormalBalance': {'type': 'number'}, + 'DiceCCTokensAddress': {'type': 'string'}, + 'myCCAddress(Dice)': {'type': 'string'}, + 'myCCBalance(Dice)': {'type': 'number'}, + 'myaddress': {'type': 'string'}, + 'mybalance': {'type': 'number'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc = dice_casino.rpc[0] + pubkey = dice_casino.pubkey[0] + + res = rpc.diceaddress() + validate_template(res, diceaddress_schema) + for key in res.keys(): + if key.find('ddress') > 0: + assert validate_raddr_pattern(res.get(key)) + res = rpc.diceaddress('') + validate_template(res, diceaddress_schema) + res = rpc.diceaddress(pubkey) + validate_template(res, diceaddress_schema) + for key in res.keys(): + if key.find('ddress') > 0: + assert validate_raddr_pattern(res.get(key)) + + def test_dicefund(self, dice_casino): + dicefund_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + dice_casino.new_casino(dice_casino.rpc[0], schema=dicefund_schema) + + def test_dicelist(self, dice_casino): + dicelist_schema = { + 'type': 'array', + 'items': {'type': 'string'} + } + + rpc = dice_casino.rpc[0] + res = rpc.dicelist() + validate_template(res, dicelist_schema) + + def test_diceinfo(self, dice_casino): + diceinfo_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'error': {'type': 'string'}, + 'fundingtxid': {'type': 'string'}, + 'name': {'type': 'string'}, + 'sbits': {'type': 'integer'}, + 'minbet': {'type': 'string'}, + 'maxbet': {'type': 'string'}, + 'maxodds': {'type': 'integer'}, + 'timeoutblocks': {'type': 'integer'}, + 'funding': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc = dice_casino.rpc[0] + if not dice_casino.open_casino: + dice_casino.new_casino(dice_casino.rpc[0]) + fundtxid = dice_casino.open_casino.get('fundingtxid') + dice_casino.diceinfo_maincheck(rpc, fundtxid, diceinfo_schema) + + def test_diceaddfunds(self, dice_casino): + diceaddfunds_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc = dice_casino.rpc[0] + amount = '15' + if not dice_casino.open_casino: + dice_casino.new_casino(dice_casino.rpc[0]) + fundtxid = dice_casino.open_casino.get('fundingtxid') + dice_casino.diceaddfunds_maincheck(rpc, amount, fundtxid, diceaddfunds_schema) + + def test_dicebet_dicestatus_dicefinish(self, dice_casino): + dicebet_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + dicestatus_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'status': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + dicefinish_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc1 = dice_casino.rpc[0] + rpc2 = dice_casino.rpc[1] + casino = dice_casino.new_casino(dice_casino.rpc[1]) + dice_casino.create_entropy(rpc2, casino) + bettxid = dice_casino.dicebet_maincheck(rpc1, casino, dicebet_schema) + dice_casino.dicestatus_maincheck(rpc1, casino, bettxid, dicestatus_schema) + wait_blocks(rpc1, 5) # 5 here is casino's block timeout + dice_casino.dicefinsish_maincheck(rpc1, casino, bettxid, dicefinish_schema) + + +@pytest.mark.usefixtures("proxy_connection", "test_params") +class TestDiceCC: + + def test_dice_errors(self, dice_casino): + rpc1 = dice_casino.rpc[0] + dicename = randomstring(4) + + # creating dice plan with too long name (>8 chars) + res = rpc1.dicefund("THISISTOOLONG", "10000", "10", "10000", "10", "5") + assert res.get('result') == 'error' + + # creating dice plan with < 100 funding + res = rpc1.dicefund(dicename, "10", "1", "10000", "10", "5") + assert res.get('result') == 'error' + + # adding negative and zero funds to plan + try: + fundtxid = rpc1.dicelist()[0] + name = rpc1.diceinfo(fundtxid).get('name') + res = rpc1.diceaddfunds(name, fundtxid, '0') + assert res.get('result') == 'error' + res = rpc1.diceaddfunds(name, fundtxid, '-123') + assert res.get('result') == 'error' + except IndexError: + casino = TestDiceCCBase.new_casino(rpc1) + fundtxid = casino.get('fundingtxid') + name = rpc1.diceinfo(fundtxid).get('name') + res = rpc1.diceaddfunds(name, fundtxid, '0') + assert res.get('result') == 'error' + res = rpc1.diceaddfunds(name, fundtxid, '-123') + assert res.get('result') == 'error' + + # not valid dice info checking + res = rpc1.diceinfo("invalid") + assert res.get('result') == 'error' + + def test_dice_badbets(self, dice_casino): + + if not dice_casino.open_casino: + dice_casino.new_casino(dice_casino.rpc[1]) + casino = dice_casino.open_casino + + rpc1 = dice_casino.rpc[0] + rpc2 = dice_casino.rpc[1] + + # before betting nodes should be synced + check_synced(rpc1, rpc2) + + try: + fundtxid = rpc2.dicelist()[0] + except IndexError: + casino = TestDiceCCBase.new_casino(rpc1) + fundtxid = casino.get('fundingtxid') + + dname = str(casino.get('name')) + minbet = str(casino.get('minbet')) + maxbet = str(casino.get('maxbet')) + maxodds = str(casino.get('maxodds')) + funding = str(casino.get('funding')) + + res = rpc1.dicebet(dname, fundtxid, '0', maxodds) # 0 bet + assert res.get('result') == 'error' + + res = rpc1.dicebet(dname, fundtxid, minbet, '0') # 0 odds + assert res.get('result') == 'error' + + res = rpc1.dicebet(dname, fundtxid, '-1', maxodds) # negative bet + assert res.get('result') == 'error' + + res = rpc1.dicebet(dname, fundtxid, minbet, '-1') # negative odds + assert res.get('result') == 'error' + + # placing bet more than maxbet + dmb = Decimal(maxbet) + dmb += 1 + res = rpc1.dicebet(dname, fundtxid, "{0:.8f}".format(dmb), maxodds) + assert res.get('result') == 'error' + + # placing bet with odds more than allowed + dmo = Decimal(maxodds) + dmo += 1 + res = rpc1.dicebet(dname, fundtxid, minbet, "{0:.8f}".format(dmo)) + assert res.get('result') == 'error' + + # placing bet with amount more than funding + betamount = funding + res = rpc1.dicebet(dname, fundtxid, str(betamount), maxodds) + assert res.get('result') == 'error' + + # placing bet with not correct dice name + name = randomstring(5) + res = rpc1.dicebet(name, fundtxid, minbet, maxodds) + assert res.get('result') == 'error' + + # placing bet with not correct dice id + badtxid = randomhex() + res = rpc1.dicebet(dname, badtxid, minbet, maxodds) + assert res.get('result') == 'error' diff --git a/qa/pytest_komodo/cc_modules/test_faucet.py b/qa/pytest_komodo/cc_modules/test_faucet.py index 137c9848ff3..49fb1cc91b3 100644 --- a/qa/pytest_komodo/cc_modules/test_faucet.py +++ b/qa/pytest_komodo/cc_modules/test_faucet.py @@ -1,106 +1,132 @@ #!/usr/bin/env python3 -# Copyright (c) 2019 SuperNET developers +# Copyright (c) 2020 SuperNET developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest -import json - -from util import assert_success, assert_error, check_if_mined, send_and_mine, rpc_connect +import re +from slickrpc import exc +import warnings +from lib.pytest_util import validate_template, mine_and_waitconfirms @pytest.mark.usefixtures("proxy_connection") -def test_faucet(test_params): - - # test params inits - rpc = test_params.get('node1').get('rpc') - rpc1 = test_params.get('node2').get('rpc') - - pubkey = test_params.get('node1').get('pubkey') - pubkey1 = test_params.get('node2').get('pubkey') - - is_fresh_chain = test_params.get("is_fresh_chain") - - # faucet got only one entity per chain - - if is_fresh_chain: - # basic sanity tests - result = rpc.getinfo() - assert result, "got response" - - result = rpc1.getinfo() - assert result, "got response" - - result = rpc.getwalletinfo() - assert result['balance'] > 0.0 - balance = result['balance'] - - result = rpc.faucetaddress() - assert result['result'] == 'success' - - # verify all keys look like valid AC addrs, could be better - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - result = rpc.faucetaddress(pubkey) - assert_success(result) - for x in result.keys(): - print(x + ": " + str(result[x])) - # test that additional CCaddress key is returned - - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' +class TestFaucetCCBase: + + def test_faucetinfo(self, test_params): + faucetinfo_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'name': {'type': 'string'}, + 'funding': {'type': 'string'} + } + } + + rpc1 = test_params.get('node1').get('rpc') + res = rpc1.faucetinfo() + validate_template(res, faucetinfo_schema) + + def test_faucetfund(self, test_params): + faucetfund_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + } + } + + rpc1 = test_params.get('node1').get('rpc') + res = rpc1.faucetfund('10') + validate_template(res, faucetfund_schema) + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1, 1) + + def test_faucetaddress(self, test_params): + faucetaddress_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'FaucetCCAddress': {'type': 'string'}, + 'FaucetCCBalance': {'type': 'number'}, + 'FaucetNormalAddress': {'type': 'string'}, + 'FaucetNormalBalance': {'type': 'number'}, + 'FaucetCCTokenAddress': {'type': 'string'}, + 'PubkeyCCaddress(Faucet)': {'type': 'string'}, + 'PubkeyCCbalance(Faucet)': {'type': 'number'}, + 'myCCaddress(Faucet)': {'type': 'string'}, + 'myCCbalance(Faucet)': {'type': 'number'}, + 'myaddress': {'type': 'string'}, + 'mybalance': {'type': 'number'} + } + } + + rpc1 = test_params.get('node1').get('rpc') + res = rpc1.faucetaddress() + validate_template(res, faucetaddress_schema) + + def test_faucetget(self, test_params): + faucetget_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + } + } + + rpc1 = test_params.get('node1').get('rpc') + node_addr = test_params.get('node1').get('address') + res = rpc1.faucetget() + # should return error if faucetget have already been used by pubkey + validate_template(res, faucetget_schema) + try: + fhex = res.get('hex') + isinstance(fhex, str) + res = rpc1.decoderawtransaction(fhex) + vout_fauc = res.get('vout')[1] + assert node_addr in vout_fauc.get('scriptPubKey').get('addresses') + assert vout_fauc.get('valueZat') == pow(10, 8) * vout_fauc.get('value') + except (KeyError, TypeError, exc.RpcTypeError): + assert res.get('result') == 'error' - # no funds in the faucet yet - result = rpc.faucetget() - assert_error(result) - result = rpc.faucetinfo() - assert_success(result) - - result = rpc.faucetfund("0") - assert_error(result) - - result = rpc.faucetfund("-1") - assert_error(result) - - # we need at least 1 + txfee to get - result = rpc.faucetfund("2") - assert_success(result) - assert result['hex'], "hex key found" - - # broadcast the xtn - result = rpc.sendrawtransaction(result['hex']) - txid = result - assert txid, "found txid" - # we need the tx above to be confirmed in the next block - check_if_mined(rpc, txid) - - result = rpc.getwalletinfo() - balance2 = result['balance'] - # make sure our balance is less now - # TODO: this check not working at the moment because of the mining rewards - # assert balance > balance2 - - result = rpc.faucetinfo() - assert_success(result) - assert float(result['funding']) > 0 - - # claiming faucet on second node - # TODO: to pass it we should increase default timeout in rpclib - # or sometimes we'll get such pycurl.error: (28, 'Operation timed out after 30000 milliseconds with 0 bytes received') - #faucetgethex = rpc1.faucetget() - #assert_success(faucetgethex) - #assert faucetgethex['hex'], "hex key found" - - balance1 = rpc1.getwalletinfo()['balance'] - - # TODO: this will not work now in tests suite because node2 mine too - # try to broadcast the faucetget transaction - #result = send_and_mine(faucetgethex['hex'], rpc1) - #assert txid, "transaction broadcasted" - - #balance2 = rpc1.getwalletinfo()['balance'] - #assert balance2 > balance1 +@pytest.mark.usefixtures("proxy_connection") +class TestFaucetCCe2e: + + # verify all addresses look like valid AC address + def test_faucet_addresses(self, test_params): + rpc1 = test_params.get('node1').get('rpc') + pubkey = test_params.get('node1').get('pubkey') + address_pattern = re.compile(r"R[a-zA-Z0-9]{33}\Z") # normal R-addr + + res = rpc1.faucetaddress() + for key in res.keys(): + if key.find('ddress') > 0: + assert address_pattern.match(str(res.get(key))) + + res = rpc1.faucetaddress(pubkey) + for key in res.keys(): + if key.find('ddress') > 0: + assert address_pattern.match(str(res.get(key))) + + def test_faucet_badvalues(self, test_params): + rpc1 = test_params.get('node1').get('rpc') + res = rpc1.faucetfund('') + assert res.get('result') == 'error' + res = rpc1.faucetfund('asdfqwe') + assert res.get('result') == 'error' + res = rpc1.faucetfund('0') + assert res.get('result') == 'error' + res = rpc1.faucetfund('-1.99') + assert res.get('result') == 'error' + + def test_faucetget_mine(self, test_params): + rpc1 = test_params.get('node1').get('rpc') + res = rpc1.faucetget() + try: + fhex = res.get('hex') + txid = rpc1.sendrawtransaction(fhex) + mine_and_waitconfirms(txid, rpc1) + except exc.RpcVerifyRejected: # excepts scenario when pubkey already received faucet funds + warnings.warn(RuntimeWarning('Faucet funds were already claimed by pubkey')) diff --git a/qa/pytest_komodo/cc_modules/test_heir.py b/qa/pytest_komodo/cc_modules/test_heir.py index da645ac2ff7..9261f01de05 100644 --- a/qa/pytest_komodo/cc_modules/test_heir.py +++ b/qa/pytest_komodo/cc_modules/test_heir.py @@ -1,152 +1,332 @@ #!/usr/bin/env python3 -# Copyright (c) 2019 SuperNET developers +# Copyright (c) 2020 SuperNET developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest import time -import json +import re +from lib.pytest_util import validate_template, mine_and_waitconfirms, randomstring, check_synced, wait_blocks -from util import assert_success, assert_error, check_if_mined, send_and_mine, \ - rpc_connect, wait_some_blocks, komodo_teardown + +@pytest.mark.usefixtures("proxy_connection") +class TestHeirCCcalls: + + def test_heirfund(self, test_params): + heirfund_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc1 = test_params.get('node1').get('rpc') + pubkey1 = test_params.get('node1').get('pubkey') + amount = '100' + name = 'heir' + randomstring(5) + inactivitytime = '20' + res = rpc1.heirfund(amount, name, pubkey1, inactivitytime, 'testMemo') + validate_template(res, heirfund_schema) + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + + def test_heiraddress(self, test_params): + heiraddress_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'HeirCCAddress': {'type': 'string'}, + 'CCbalance': {'type': 'number'}, + 'HeirNormalAddress': {'type': 'string'}, + 'HeirCC`1of2`Address': {'type': 'string'}, + 'HeirCC`1of2`TokensAddress': {'type': 'string'}, + 'myAddress': {'type': 'string'}, + 'myCCAddress(Heir)': {'type': 'string'}, + 'PubkeyCCAddress(Heir)': {'type': 'string'}, + 'myCCaddress': {'type': 'string'}, + 'myCCbalance': {'type': 'number'}, + 'myaddress': {'type': 'string'}, + 'mybakance': {'type': 'number'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc1 = test_params.get('node1').get('rpc') + pubkey1 = test_params.get('node1').get('pubkey') + address_pattern = re.compile(r"R[a-zA-Z0-9]{33}\Z") # normal R-addr + res = rpc1.heiraddress(pubkey1) + validate_template(res, heiraddress_schema) + assert res.get('result') == 'success' + + # verify all keys look like valid AC addrs + res = rpc1.heiraddress('') + for key in res.keys(): + if key.find('ddress') > 0: + assert address_pattern.match(str(res.get(key))) + + # test that additional CCaddress key is returned + res = rpc1.heiraddress(pubkey1) + for key in res.keys(): + if key.find('ddress') > 0: + assert address_pattern.match(str(res.get(key))) + + def test_heirlist(self, test_params): + heirlist_schema = { + 'type': 'array', + 'items': { + 'type': 'string' + } + } + + rpc1 = test_params.get('node1').get('rpc') + res = rpc1.heirlist() + validate_template(res, heirlist_schema) + + def test_heiradd(self, test_params): + hieradd_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc1 = test_params.get('node1').get('rpc') + amount = '100' + try: + fundid = rpc1.heirlist()[0] + res = rpc1.heiradd(amount, fundid) + validate_template(res, hieradd_schema) + assert res.get('result') == 'success' + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + except IndexError: + print('\nNo heirplan on chain, creating one\n') + pubkey1 = test_params.get('node1').get('pubkey') + amount = '100' + name = 'heir' + randomstring(5) + inactivitytime = '20' + res = rpc1.heirfund(amount, name, pubkey1, inactivitytime, 'testMemoHeirInfo') + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + fundid = rpc1.heirlist()[0] + res = rpc1.heiradd(amount, fundid) + validate_template(res, hieradd_schema) + assert res.get('result') == 'success' + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + + def test_heirinfo(self, test_params): + heirinfo_schema = { + 'type': 'object', + 'properties': { + 'name': {'type': 'string'}, + 'fundingtxid': {'type': 'string'}, + 'owner': {'type': 'string'}, + 'tokenid': {'type': 'string'}, + 'heir': {'type': 'string'}, + 'type': {'type': 'string'}, + 'lifetime': {'type': 'string'}, + 'available': {'type': 'string'}, + 'OwnerRemainderTokens': {'type': 'string'}, + 'InactivityTimeSetting': {'type': 'string'}, + 'IsHeirSpendingAllowed': {'type': 'string'}, + 'memo': {'type': 'string'}, + 'result': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc1 = test_params.get('node1').get('rpc') + try: + fundid = rpc1.heirlist()[0] + res = rpc1.heirinfo(fundid) + validate_template(res, heirinfo_schema) + assert res.get('result') == 'success' + except IndexError: + print('\nNo heirplan on chain, creating one\n') + pubkey1 = test_params.get('node1').get('pubkey') + amount = '100' + name = 'heir' + randomstring(5) + inactivitytime = '20' + res = rpc1.heirfund(amount, name, pubkey1, inactivitytime, 'testMemoHeirInfo') + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + fundid = rpc1.heirlist()[0] + res = rpc1.heirinfo(fundid) + validate_template(res, heirinfo_schema) + assert res.get('result') == 'success' + + def test_heirclaim(self, test_params): + heirclaim_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc1 = test_params.get('node1').get('rpc') + # create heir plan to claim + pubkey1 = test_params.get('node2').get('pubkey') + amount = '100' + name = 'heir' + randomstring(5) + inactivitytime = '120' + res = rpc1.heirfund(amount, name, pubkey1, inactivitytime, 'testMemo') + fundtxid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(fundtxid, rpc1) + + # Wait inactivitytime and claim funds + time.sleep(int(inactivitytime)) + print("\n Sleeping for inactivity time") + res = rpc1.heirclaim(amount, fundtxid) + validate_template(res, heirclaim_schema) + claimtxid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(claimtxid, rpc1) @pytest.mark.usefixtures("proxy_connection") -def test_heir(test_params): - - # test params inits - rpc = test_params.get('node1').get('rpc') - rpc1 = test_params.get('node2').get('rpc') - - pubkey = test_params.get('node1').get('pubkey') - pubkey1 = test_params.get('node2').get('pubkey') - - is_fresh_chain = test_params.get("is_fresh_chain") - - result = rpc.heiraddress('') - assert_success(result) - - # verify all keys look like valid AC addrs, could be better - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - result = rpc.heiraddress(pubkey) - assert_success(result) - - # test that additional CCaddress key is returned - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - # getting empty heir list - if is_fresh_chain: - result = rpc.heirlist() - assert result == [] - - # valid heirfund case with coins - result = rpc.heirfund("1000", "UNITHEIR", pubkey1, "10", "TESTMEMO") - assert_success(result) - heir_fund_txid = send_and_mine(result["hex"], rpc) - assert heir_fund_txid, "got heir funding txid" - - # heir fund txid should be in heirlist now - result = rpc.heirlist() - assert heir_fund_txid in result - - # checking heirinfo - result = rpc.heirinfo(heir_fund_txid) - assert_success(result) - assert result["fundingtxid"] == heir_fund_txid - assert result["name"] == "UNITHEIR" - assert result["owner"] == pubkey - assert result["heir"] == pubkey1 - assert result["memo"] == "TESTMEMO" - assert result["lifetime"] == "1000.00000000" - assert result["type"] == "coins" - assert result["InactivityTimeSetting"] == "10" - # TODO: we have non insta blocks now so should set inactivity time more than blocktime to proper test it - # assert result["IsHeirSpendingAllowed"] == "false" - - # waiting for 20 seconds to be sure that needed time passed for heir claiming - time.sleep(20) - wait_some_blocks(rpc, 1) - result = rpc.heirinfo(heir_fund_txid) - assert result["lifetime"] == "1000.00000000" - assert result["IsHeirSpendingAllowed"] == "true" - - # have to check that second node have coins to cover txfee at least - second_node_balance = rpc1.getbalance() - if second_node_balance < 0.1: - rpc.sendtoaddress(rpc1.getnewaddress(), 1) - time.sleep(10) # to ensure transactions are in different blocks - rpc.sendtoaddress(rpc1.getnewaddress(), 1) - wait_some_blocks(rpc, 2) - assert second_node_balance > 0.1 - - # let's claim whole heir sum from second node - result = rpc1.heirclaim("1000", heir_fund_txid) - assert_success(result) - heir_claim_txid = send_and_mine(result["hex"], rpc1) - assert heir_claim_txid, "got claim txid" - - # balance of second node after heirclaim should increase for 1000 coins - txfees - # + get one block reward when broadcasted heir_claim_txid - # TODO: very bad test with non-clearly hardcoded blockreward - needs to be changed - # result = round(rpc1.getbalance()) - round(second_node_balance) - # assert result > 100999 - - # no more funds should be available for claiming - result = rpc.heirinfo(heir_fund_txid) - assert result["lifetime"] == "1000.00000000" - assert result["available"] == "0.00000000" - - # creating tokens which we put to heir contract - token_hex = rpc.tokencreate("TEST", "1", "TESTING") - token_txid = send_and_mine(token_hex["hex"], rpc) - assert token_txid, "got token txid" - - # checking possesion over the tokens and balance - result = rpc.tokenbalance(token_txid, pubkey)["balance"] - assert result == 100000000 - - # valid heir case with tokens - token_heir_hex = rpc.heirfund("100000000", "UNITHEIR", pubkey1, "10", "TESTMEMO", token_txid) - token_heir_txid = send_and_mine(token_heir_hex["hex"], rpc) - assert token_heir_txid, "got txid of heirfund with tokens" - - # checking heirinfo - result = rpc.heirinfo(token_heir_txid) - assert_success(result) - assert result["fundingtxid"] == token_heir_txid - assert result["name"] == "UNITHEIR" - assert result["owner"] == pubkey - assert result["heir"] == pubkey1 - assert result["lifetime"] == "100000000" - assert result["type"] == "tokens" - assert result["InactivityTimeSetting"] == "10" - # TODO: we have non insta blocks now so should set inactivity time more than blocktime to proper test it - # assert result["IsHeirSpendingAllowed"] == "false" - - # waiting for 11 seconds to be sure that needed time passed for heir claiming - time.sleep(11) - wait_some_blocks(rpc, 2) - result = rpc.heirinfo(token_heir_txid) - assert result["lifetime"] == "100000000" - assert result["IsHeirSpendingAllowed"] == "true" - - # let's claim whole heir sum from second node - result = rpc1.heirclaim("100000000", token_heir_txid) - assert_success(result) - - heir_tokens_claim_txid = send_and_mine(result["hex"], rpc1) - assert heir_tokens_claim_txid, "got claim txid" - - # claiming node should have correct token balance now - result = rpc1.tokenbalance(token_txid, pubkey1)["balance"] - assert result == 100000000 - - # no more funds should be available for claiming - result = rpc.heirinfo(token_heir_txid) - assert result["lifetime"] == "100000000" - assert result["available"] == "0" +class TestHeirFunc: + + def test_heir_flow(self, test_params): + # Check basic heirCC flow from fund to claim + # Create valid heir plan + rpc1 = test_params.get('node1').get('rpc') + pubkey1 = test_params.get('node1').get('pubkey') + rpc2 = test_params.get('node2').get('rpc') + pubkey2 = test_params.get('node2').get('pubkey') + inactivitytime = 70 # ideally, should be a bit more than blocktime + amount = 777 + plan_name = 'heir' + randomstring(5) + comment = 'HeirFlowTest' + randomstring(5) + res = rpc1.heirfund(str(amount), plan_name, pubkey2, + str(inactivitytime), comment) + fundtx = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(fundtx, rpc1) + time.sleep(5) + + # Check plan availability in heirlist + res = rpc1.heirlist() + assert fundtx in res + + # Check plan info + res = rpc1.heirinfo(fundtx) + assert res.get('result') == 'success' + # check here stuff + assert res['fundingtxid'] == fundtx + assert res['name'] == plan_name + assert res['owner'] == pubkey1 + assert res['heir'] == pubkey2 + assert res['memo'] == comment + assert res['lifetime'] == str(amount) + '.00000000' + assert res['type'] == "coins" + assert res['InactivityTimeSetting'] == str(inactivitytime) + + # Check Heir spending allowed after inactivity time + print("\n Sleeping for inactivity time") + time.sleep(inactivitytime + 1) + wait_blocks(rpc1, 2) + check_synced(rpc1, rpc2) # prevents issues when inactivity time =< block time + res = rpc1.heirinfo(fundtx) + assert res['lifetime'] == str(amount) + '.00000000' + assert res['available'] == str(amount) + '.00000000' + assert res['IsHeirSpendingAllowed'] == 'true' + + # Claim all available funds from hier node + res = rpc2.heirclaim(str(amount), fundtx) + assert res.get('result') == 'success' + claimtx = rpc2.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(claimtx, rpc2) + time.sleep(5) + # Check claim success + # Wait sync + wait_blocks(rpc1, 2) + check_synced(rpc1, rpc2) + res = rpc1.heirinfo(fundtx) + assert res['lifetime'] == str(amount) + '.00000000' + assert res['available'] == '0.00000000' + res = rpc2.heirinfo(fundtx) + assert res['lifetime'] == str(amount) + '.00000000' + assert res['available'] == '0.00000000' + + def test_heir_tokens_flow(self, test_params): + rpc1 = test_params.get('node1').get('rpc') + pubkey1 = test_params.get('node1').get('pubkey') + rpc2 = test_params.get('node2').get('rpc') + pubkey2 = test_params.get('node2').get('pubkey') + inactivitytime = 70 # ideally, should be a bit more than blocktime + amount = 100000000 + plan_name = 'heir' + randomstring(5) + comment = 'HeirFlowTest' + randomstring(5) + token_name = 'token' + randomstring(5) + + # Create on-chain tokens + res = rpc1.tokencreate(token_name, '1', 'heirCCTest') + tokentx = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(tokentx, rpc1) + res = rpc1.tokenbalance(tokentx, pubkey1)['balance'] + assert res == amount # validate init tokenbalance + + res = rpc1.heirfund(str(amount), plan_name, pubkey2, + str(inactivitytime), comment, tokentx) + fundtx = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(fundtx, rpc1) + time.sleep(5) + + # Check plan availability in heirlist + res = rpc1.heirlist() + assert fundtx in res + + # Check plan info + res = rpc1.heirinfo(fundtx) + assert res.get('result') == 'success' + # check here stuff + assert res['fundingtxid'] == fundtx + assert res['name'] == plan_name + assert res['owner'] == pubkey1 + assert res['heir'] == pubkey2 + assert res['memo'] == comment + assert res['lifetime'] == str(amount) + assert res['tokenid'] == tokentx + assert res['type'] == 'tokens' + assert res['InactivityTimeSetting'] == str(inactivitytime) + + # Check Heir spending allowed after inactivity time + print("\n Sleeping for inactivity time") + time.sleep(inactivitytime + 1) + wait_blocks(rpc1, 2) + check_synced(rpc1, rpc2) + res = rpc1.heirinfo(fundtx) + assert res['lifetime'] == str(amount) + assert res['available'] == str(amount) + assert res['IsHeirSpendingAllowed'] == 'true' + + # Claim all available funds from hier node + res = rpc2.heirclaim(str(amount), fundtx) + assert res.get('result') == 'success' + claimtx = rpc2.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(claimtx, rpc2) + time.sleep(5) + # Check claim success + # Wait sync + wait_blocks(rpc1, 1) + check_synced(rpc1, rpc2) + res = rpc1.heirinfo(fundtx) + assert res['lifetime'] == str(amount) + assert res['available'] == '0' + res = rpc2.heirinfo(fundtx) + assert res['lifetime'] == str(amount) + assert res['available'] == '0' + + # Check heir balance after claim + res = rpc2.tokenbalance(tokentx, pubkey2)['balance'] + assert res == amount diff --git a/qa/pytest_komodo/cc_modules/test_oracles.py b/qa/pytest_komodo/cc_modules/test_oracles.py index df262e3c97b..1b3fa5e4a8b 100644 --- a/qa/pytest_komodo/cc_modules/test_oracles.py +++ b/qa/pytest_komodo/cc_modules/test_oracles.py @@ -1,298 +1,289 @@ #!/usr/bin/env python3 -# Copyright (c) 2019 SuperNET developers +# Copyright (c) 2021 SuperNET developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest -import os -import time -from util import assert_success, assert_error, check_if_mined,\ - send_and_mine, rpc_connect, wait_some_blocks, generate_random_string, komodo_teardown - - -@pytest.mark.usefixtures("proxy_connection") -def test_oracles(test_params): - - # test params inits - rpc = test_params.get('node1').get('rpc') - rpc1 = test_params.get('node2').get('rpc') - - pubkey = test_params.get('node1').get('pubkey') - pubkey1 = test_params.get('node2').get('pubkey') - - is_fresh_chain = test_params.get("is_fresh_chain") - - result = rpc.oraclesaddress() - assert_success(result) - - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - result = rpc.oraclesaddress(pubkey) - assert_success(result) - - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - # there are no oracles created yet - if is_fresh_chain: - result = rpc.oracleslist() - assert result == [] - - # looking up non-existent oracle should return error. - result = rpc.oraclesinfo("none") - assert_error(result) - - # attempt to create oracle with not valid data type should return error - result = rpc.oraclescreate("Test", "Test", "Test") - assert_error(result) - - # attempt to create oracle with description > 32 symbols should return error - too_long_name = generate_random_string(33) - result = rpc.oraclescreate(too_long_name, "Test", "s") - assert_error(result) - - # attempt to create oracle with description > 4096 symbols should return error - too_long_description = generate_random_string(4100) - result = rpc.oraclescreate("Test", too_long_description, "s") - assert_error(result) - - # valid creating oracles of different types - # using such naming to re-use it for data publishing / reading (e.g. oracle_s for s type) - print(len(rpc.listunspent())) - # enable mining - valid_formats = ["s", "S", "d", "D", "c", "C", "t", "T", "i", "I", "l", "L", "h", "Ihh"] - for f in valid_formats: - result = rpc.oraclescreate("Test_" + f, "Test_" + f, f) - assert_success(result) - # globals()["oracle_{}".format(f)] = rpc.sendrawtransaction(result['hex']) - globals()["oracle_{}".format(f)] = send_and_mine(result['hex'], rpc) - - list_fund_txid = [] - for f in valid_formats: +from slickrpc.exc import RpcException as RPCError +from lib.pytest_util import validate_template, mine_and_waitconfirms, randomstring,\ + randomhex, validate_raddr_pattern + + +@pytest.mark.usefixtures("proxy_connection", "test_params") +class TestOracleInstance: + + def test_oraclescreate_list_info(self, oracle_instance): + create_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + list_schema = { + 'type': 'array', + 'items': {'type': 'string'} + } + + info_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'txid': {'type': 'string'}, + 'description': {'type': 'string'}, + 'name': {'type': 'string'}, + 'format': {'type': 'string'}, + 'marker': {'type': 'string'}, + 'registered': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'publisher': {'type': 'string'}, + 'baton': {'type': 'string'}, + 'batontxid': {'type': 'string'}, + 'lifetime': {'type': 'string'}, + 'funds': {'type': 'string'}, + 'datafee': {'type': 'string'} + } + } + } + }, + 'required': ['result'] + } + + rpc1 = oracle_instance.rpc[0] + rpc2 = oracle_instance.rpc[1] + # test oracle creation + oracle_instance.new_oracle(rpc2, schema=create_schema) + + res = rpc1.oracleslist() + validate_template(res, list_schema) + + res = rpc1.oraclesinfo(oracle_instance.base_oracle.get('oracle_id')) + validate_template(res, info_schema) + + def test_oraclesaddress(self, oracle_instance): + + oraclesaddress_schema = { + 'type': 'object', + 'properties': { + "result": {'type': 'string'}, + "OraclesAddress": {'type': 'string'}, + "OraclesBalance": {'type': 'number'}, + "OraclesNormalAddress": {'type': 'string'}, + "OraclesNormalBalance": {'type': 'number'}, + "OraclesTokensAddress": {'type': 'string'}, + "PubkeyCCaddress(Oracles)": {'type': 'string'}, + "PubkeyCCbalance(Oracles)": {'type': 'number'}, + "myCCAddress(Oracles)": {'type': 'string'}, + "myCCbalance(Oracles)": {'type': 'number'}, + "myaddress": {'type': 'string'}, + "mybalance": {'type': 'number'} + }, + 'required': ['result'] + } + + rpc1 = oracle_instance.rpc[0] + rpc2 = oracle_instance.rpc[1] + pubkey = oracle_instance.pubkey[0] + + if not oracle_instance.base_oracle: + oracle_instance.new_oracle(rpc2) + + res = rpc1.oraclesaddress(pubkey) + validate_template(res, oraclesaddress_schema) + + res = rpc1.oraclesaddress(pubkey) + for key in res.keys(): + if key.find('ddress') > 0: + assert validate_raddr_pattern(res.get(key)) + + res = rpc1.oraclesaddress() + for key in res.keys(): + if key.find('ddress') > 0: + assert validate_raddr_pattern(res.get(key)) + + def test_oracles_data_interactions(self, oracle_instance): + general_hex_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + sample_schema = { + 'type': 'object', + 'properties': { + 'samples': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'txid': {'type': 'string'}, + 'data': {'type': 'string'} + } + } + } + } + } + + rpc1 = oracle_instance.rpc[0] + rpc2 = oracle_instance.rpc[1] + amount = '10000000' + sub_amount = '0.1' + + if not oracle_instance.base_oracle: + oracle_instance.new_oracle(rpc2) + + oracle_id = oracle_instance.base_oracle.get('oracle_id') + + # Fund fresh oracle + res = rpc1.oraclesfund(oracle_id) + validate_template(res, general_hex_schema) + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + + # Register as publisher + res = rpc1.oraclesregister(oracle_id, amount) + validate_template(res, general_hex_schema) + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + + # Subscrive to new oracle + oraclesinfo = rpc1.oraclesinfo(oracle_id) + publisher = oraclesinfo.get('registered')[0].get('publisher') + res = rpc1.oraclessubscribe(oracle_id, publisher, sub_amount) + validate_template(res, general_hex_schema) + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, oracle_instance.rpc[0]) + + # Publish new data + res = rpc1.oraclesdata(oracle_id, '0a74657374737472696e67') # teststring + validate_template(res, general_hex_schema) + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + + # Check data + oraclesinfo = rpc1.oraclesinfo(oracle_id) + baton = oraclesinfo.get('registered')[0].get('batontxid') + res = rpc1.oraclessample(oracle_id, baton) + validate_template(res, sample_schema) + assert res.get('txid') == baton + + def test_bad_calls(self, oracle_instance): + if not oracle_instance.base_oracle: + oracle_instance.new_oracle(oracle_instance.rpc[1]) + + oracle = oracle_instance # trying to register with negative datafee - result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "-100") - assert_error(result) + res = oracle.rpc[0].oraclesregister(oracle.base_oracle.get('oracle_id'), "-100") + assert res.get('error') # trying to register with zero datafee - result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "0") - assert_error(result) + res = oracle.rpc[0].oraclesregister(oracle.base_oracle.get('oracle_id'), "0") + assert res.get('error') # trying to register with datafee less than txfee - result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "500") - assert_error(result) + res = oracle.rpc[0].oraclesregister(oracle.base_oracle.get('oracle_id'), "500") + assert res.get('error') # trying to register valid (unfunded) - result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "10000") - assert_error(result) - - # Fund the oracles - result = rpc.oraclesfund(globals()["oracle_{}".format(f)]) - assert_success(result) - fund_txid = rpc.sendrawtransaction(result["hex"]) - list_fund_txid.append(fund_txid) - assert fund_txid, "got txid" - - wait_some_blocks(rpc, 2) - - for t in list_fund_txid: - c = 0 - print("Waiting confiramtions for oraclesfund") - while c < 2: - try: - c = rpc.getrawtransaction(t, 1)['confirmations'] - except KeyError: - time.sleep(29) - print("Oracles fund confirmed \n", t) - - for f in valid_formats: - # trying to register valid (funded) - result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "100000") - assert_success(result) - print("Registering ", f) - register_txid = rpc.sendrawtransaction(result["hex"]) - assert register_txid, "got txid" - - # TODO: for most of the non valid oraclesregister and oraclessubscribe transactions generating and broadcasting now - # so trying only valid oraclessubscribe atm - result = rpc.oraclessubscribe(globals()["oracle_{}".format(f)], pubkey, "1") - assert_success(result) - subscribe_txid = rpc.sendrawtransaction(result["hex"]) - assert register_txid, "got txid" - - wait_some_blocks(rpc, 2) - - # now lets publish and read valid data for each oracle type - - # recording data for s type - result = rpc.oraclesdata(globals()["oracle_{}".format("s")], "05416e746f6e") - assert_success(result) - oraclesdata_s = rpc.sendrawtransaction(result["hex"]) - info_s = rpc.oraclesinfo(globals()["oracle_{}".format("s")]) - batonaddr_s = info_s['registered'][0]['baton'] - - # recording data for S type - result = rpc.oraclesdata(globals()["oracle_{}".format("S")], - "000161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161") - assert_success(result) - oraclesdata_S = rpc.sendrawtransaction(result["hex"]) - info = rpc.oraclesinfo(globals()["oracle_{}".format("S")]) - batonaddr_S = info['registered'][0]['baton'] - - # recording data for d type - result = rpc.oraclesdata(globals()["oracle_{}".format("d")], "0101") - assert_success(result) - # baton - oraclesdata_d = rpc.sendrawtransaction(result["hex"]) - info = rpc.oraclesinfo(globals()["oracle_{}".format("d")]) - batonaddr_d = info['registered'][0]['baton'] - - # recording data for D type - result = rpc.oraclesdata(globals()["oracle_{}".format("D")], "010001") - assert_success(result) - # baton - oraclesdata_D = rpc.sendrawtransaction(result["hex"]) - info = rpc.oraclesinfo(globals()["oracle_{}".format("D")]) - batonaddr_D = info['registered'][0]['baton'] - - # recording data for c type - result = rpc.oraclesdata(globals()["oracle_{}".format("c")], "ff") - assert_success(result) - # baton - oraclesdata_c = rpc.sendrawtransaction(result["hex"]) - info = rpc.oraclesinfo(globals()["oracle_{}".format("c")]) - batonaddr_c = info['registered'][0]['baton'] - - # recording data for C type - result = rpc.oraclesdata(globals()["oracle_{}".format("C")], "ff") - assert_success(result) - # baton - oraclesdata_C = rpc.sendrawtransaction(result["hex"]) - info = rpc.oraclesinfo(globals()["oracle_{}".format("C")]) - batonaddr_C = info['registered'][0]['baton'] - - # recording data for t type - result = rpc.oraclesdata(globals()["oracle_{}".format("t")], "ffff") - assert_success(result) - # baton - oraclesdata_t = rpc.sendrawtransaction(result["hex"]) - info = rpc.oraclesinfo(globals()["oracle_{}".format("t")]) - batonaddr_t = info['registered'][0]['baton'] - - # recording data for T type - result = rpc.oraclesdata(globals()["oracle_{}".format("T")], "ffff") - assert_success(result) - # baton - oraclesdata_T = rpc.sendrawtransaction(result["hex"]) - info = rpc.oraclesinfo(globals()["oracle_{}".format("T")]) - batonaddr_T = info['registered'][0]['baton'] - - # recording data for i type - result = rpc.oraclesdata(globals()["oracle_{}".format("i")], "ffffffff") - assert_success(result) - # baton - oraclesdata_i = rpc.sendrawtransaction(result["hex"]) - info = rpc.oraclesinfo(globals()["oracle_{}".format("i")]) - batonaddr_i = info['registered'][0]['baton'] - - # recording data for I type - result = rpc.oraclesdata(globals()["oracle_{}".format("I")], "ffffffff") - assert_success(result) - # baton - oraclesdata_I = rpc.sendrawtransaction(result["hex"]) - info = rpc.oraclesinfo(globals()["oracle_{}".format("I")]) - batonaddr_I = info['registered'][0]['baton'] - - # recording data for l type - result = rpc.oraclesdata(globals()["oracle_{}".format("l")], "00000000ffffffff") - assert_success(result) - # baton - oraclesdata_l = rpc.sendrawtransaction(result["hex"]) - info = rpc.oraclesinfo(globals()["oracle_{}".format("l")]) - batonaddr_l = info['registered'][0]['baton'] - - # recording data for L type - result = rpc.oraclesdata(globals()["oracle_{}".format("L")], "00000000ffffffff") - assert_success(result) - # baton - oraclesdata_L = rpc.sendrawtransaction(result["hex"]) - info = rpc.oraclesinfo(globals()["oracle_{}".format("L")]) - batonaddr_L = info['registered'][0]['baton'] - - # recording data for h type - result = rpc.oraclesdata(globals()["oracle_{}".format("h")], - "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff") - assert_success(result) - # baton - oraclesdata_h = rpc.sendrawtransaction(result["hex"]) - info = rpc.oraclesinfo(globals()["oracle_{}".format("h")]) - batonaddr_h = info['registered'][0]['baton'] - - # recording data for Ihh type - result = rpc.oraclesdata(globals()["oracle_{}".format("Ihh")], - "ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff") - assert_success(result) - # baton - oraclesdata_Ihh = rpc.sendrawtransaction(result["hex"]) - info = rpc.oraclesinfo(globals()["oracle_{}".format("Ihh")]) - batonaddr_Ihh = info['registered'][0]['baton'] - - wait_some_blocks(rpc, 1) - - # checking data for s type - result = rpc.oraclessamples(globals()["oracle_{}".format("s")], batonaddr_s, "1") - assert "['Anton']" == str(result["samples"][0]['data']) - - # checking data for S type - result = rpc.oraclessamples(globals()["oracle_{}".format("S")], batonaddr_S, "1") - assert "['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa']" == str(result["samples"][0]['data']) - - # checking data for d type - result = rpc.oraclessamples(globals()["oracle_{}".format("d")], batonaddr_d, "1") - assert "['01']" == str(result["samples"][0]['data']) - - # checking data for D type - result = rpc.oraclessamples(globals()["oracle_{}".format("D")], batonaddr_D, "1") - assert "['01']" == str(result["samples"][0]['data']) - - # checking data for c type - result = rpc.oraclessamples(globals()["oracle_{}".format("c")], batonaddr_c, "1") - assert "['-1']" == str(result["samples"][0]['data']) - - # checking data for C type - result = rpc.oraclessamples(globals()["oracle_{}".format("C")], batonaddr_C, "1") - assert "['255']" == str(result["samples"][0]['data']) - - # checking data for t type - result = rpc.oraclessamples(globals()["oracle_{}".format("t")], batonaddr_t, "1") - assert "['-1']" == str(result["samples"][0]['data']) - - # checking data for T type - result = rpc.oraclessamples(globals()["oracle_{}".format("T")], batonaddr_T, "1") - assert "['65535']" == str(result["samples"][0]['data']) - - # checking data for i type - result = rpc.oraclessamples(globals()["oracle_{}".format("i")], batonaddr_i, "1") - assert "['-1']" == str(result["samples"][0]['data']) - - # checking data for I type - result = rpc.oraclessamples(globals()["oracle_{}".format("I")], batonaddr_I, "1") - assert "['4294967295']" == str(result["samples"][0]['data']) - - # checking data for l type - result = rpc.oraclessamples(globals()["oracle_{}".format("l")], batonaddr_l, "1") - assert "['-4294967296']" == str(result["samples"][0]['data']) - - # checking data for L type - result = rpc.oraclessamples(globals()["oracle_{}".format("L")], batonaddr_L, "1") - assert "['18446744069414584320']" == str(result["samples"][0]['data']) - - # checking data for h type - result = rpc.oraclessamples(globals()["oracle_{}".format("h")], batonaddr_h, "1") - assert "['ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000']" == str(result["samples"][0]['data']) - - # checking data for Ihh type - result = rpc.oraclessamples(globals()["oracle_{}".format("Ihh")], batonaddr_Ihh, "1") - assert "['4294967295', 'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000', 'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000']" == str(result["samples"][0]['data']) + res = oracle.rpc[0].oraclesregister(oracle.base_oracle.get('oracle_id'), "1000000") + assert res.get('error') + + # trying to register with invalid datafee + res = oracle.rpc[0].oraclesregister(oracle.base_oracle.get('oracle_id'), "asdasd") + assert res.get('error') + + # looking up non-existent oracle should return error. + res = oracle.rpc[0].oraclesinfo("none") + assert res.get('error') + + # attempt to create oracle with not valid data type should return error + res = oracle.rpc[0].oraclescreate("Test", "Test", "Test") + assert res.get('error') + + # attempt to create oracle with name > 32 symbols should return error + too_long_name = randomstring(33) + res = oracle.rpc[0].oraclescreate(too_long_name, "Test", "s") + assert res.get('error') + + # attempt to create oracle with description > 4096 symbols should return error + too_long_description = randomstring(4100) + res = oracle.rpc[0].oraclescreate("Test", too_long_description, "s") + assert res.get('error') + + def test_oracles_data(self, oracle_instance): + oracles_data = { + 's': '05416e746f6e', + 'S': '000161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161', + 'd': '0101', + 'D': '010001', + 'c': 'ff', + 'C': 'ff', + 't': 'ffff', + 'T': 'ffff', + 'i': 'ffffffff', + 'I': 'ffffffff', + 'l': '00000000ffffffff', + 'L': '00000000ffffffff', + 'h': 'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000', + } + + oracles_response = { + 's_un': 'Anton', + 'S_un': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + 'd_un': '01', + 'D_un': '01', + 'c_un': '-1', + 'C_un': '255', + 't_un': '-1', + 'T_un': '65535', + 'i_un': '-1', + 'I_un': '4294967295', + 'l_un': '-4294967296', + 'L_un': '18446744069414584320', + 'h_un': '00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff' + } + + rpc = oracle_instance.rpc[0] + oracles = oracle_instance.new_oracle(rpc, o_type=list(oracles_data.keys())) + + txid = "" + for oracle in oracles: + res = rpc.oraclesfund(oracle.get('oracle_id')) + txid = rpc.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc) + + for oracle in oracles: + res = rpc.oraclesregister(oracle.get('oracle_id'), '10000000') + txid = rpc.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc) + + for oracle in oracles: + oraclesinfo = rpc.oraclesinfo(oracle.get('oracle_id')) + publisher = oraclesinfo.get('registered')[0].get('publisher') + res = rpc.oraclessubscribe(oracle.get('oracle_id'), publisher, '0.1') + txid = rpc.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc) + + o_data = "" + for oracle, o_type in zip(oracles, oracles_data.keys()): + res = rpc.oraclesdata(oracle.get('oracle_id'), oracles_data.get(o_type)) + assert res.get('result') == 'success' + o_data = rpc.sendrawtransaction(res.get("hex")) + mine_and_waitconfirms(o_data, rpc) + + for oracle, o_type in zip(oracles, oracles_data.keys()): + oraclesinfo = rpc.oraclesinfo(oracle.get('oracle_id')) + baton = oraclesinfo.get('registered')[0].get('batontxid') + + res = rpc.oraclessample(oracle.get('oracle_id'), baton) + assert (res.get('data')[0] == oracles_response.get(str(o_type) + '_un')) diff --git a/qa/pytest_komodo/cc_modules/test_rewards.py b/qa/pytest_komodo/cc_modules/test_rewards.py index 3c2759852bc..6f3a733d688 100644 --- a/qa/pytest_komodo/cc_modules/test_rewards.py +++ b/qa/pytest_komodo/cc_modules/test_rewards.py @@ -1,134 +1,190 @@ #!/usr/bin/env python3 -# Copyright (c) 2019 SuperNET developers +# Copyright (c) 2021 SuperNET developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest -import json -from util import assert_success, assert_error, check_if_mined, send_and_mine,\ - rpc_connect, wait_some_blocks, generate_random_string, komodo_teardown - - -@pytest.mark.usefixtures("proxy_connection") -def test_rewards(test_params): - - # test params inits - rpc = test_params.get('node1').get('rpc') - rpc1 = test_params.get('node2').get('rpc') - - pubkey = test_params.get('node1').get('pubkey') - pubkey1 = test_params.get('node2').get('pubkey') - - is_fresh_chain = test_params.get("is_fresh_chain") - - global proxy - proxy = [rpc, rpc1] - - result = rpc.rewardsaddress() - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - result = rpc.rewardsaddress(pubkey) - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - # no rewards yet - if is_fresh_chain: - result = rpc.rewardslist() - assert result == [] - - # looking up non-existent reward should return error - result = rpc.rewardsinfo("none") - assert_error(result) - - # creating rewards plan with name > 8 chars, should return error - result = rpc.rewardscreatefunding("STUFFSTUFF", "7777", "25", "0", "10", "10") - assert_error(result) - - # creating rewards plan with 0 funding - result = rpc.rewardscreatefunding("STUFF", "0", "25", "0", "10", "10") - assert_error(result) - - # creating rewards plan with 0 maxdays - result = rpc.rewardscreatefunding("STUFF", "7777", "25", "0", "10", "0") - assert_error(result) - - # creating rewards plan with > 25% APR - result = rpc.rewardscreatefunding("STUFF", "7777", "30", "0", "10", "10") - assert_error(result) - - # creating valid rewards plan - plan_name = generate_random_string(6) - result = rpc.rewardscreatefunding(plan_name, "7777", "25", "0", "10", "10") - assert result['hex'], 'got raw xtn' - fundingtxid = send_and_mine(result['hex'], rpc) - assert fundingtxid, 'got txid' - result = rpc.rewardsinfo(fundingtxid) - assert_success(result) - assert result['name'] == plan_name - assert result['APR'] == "25.00000000" - assert result['minseconds'] == 0 - assert result['maxseconds'] == 864000 - assert result['funding'] == "7777.00000000" - assert result['mindeposit'] == "10.00000000" - assert result['fundingtxid'] == fundingtxid - - # checking if new plan in rewardslist - result = rpc.rewardslist() - assert fundingtxid in result - - # creating reward plan with already existing name, should return error - result = rpc.rewardscreatefunding(plan_name, "7777", "25", "0", "10", "10") - assert_error(result) - - # add funding amount must be positive - result = rpc.rewardsaddfunding(plan_name, fundingtxid, "-1") - assert_error(result) - - # add funding amount must be positive - result = rpc.rewardsaddfunding(plan_name, fundingtxid, "0") - assert_error(result) - - # adding valid funding - result = rpc.rewardsaddfunding(plan_name, fundingtxid, "555") - addfundingtxid = send_and_mine(result['hex'], rpc) - assert addfundingtxid, 'got funding txid' - - # checking if funding added to rewardsplan - result = rpc.rewardsinfo(fundingtxid) - assert result['funding'] == "8332.00000000" - - # trying to lock funds, locking funds amount must be positive - result = rpc.rewardslock(plan_name, fundingtxid, "-5") - assert_error(result) - - # trying to lock funds, locking funds amount must be positive - result = rpc.rewardslock(plan_name, fundingtxid, "0") - assert_error(result) - - # trying to lock less than the min amount is an error - result = rpc.rewardslock(plan_name, fundingtxid, "7") - assert_error(result) - - # locking funds in rewards plan - result = rpc.rewardslock(plan_name, fundingtxid, "10") - assert_success(result) - locktxid = result['hex'] - assert locktxid, "got lock txid" - - # locktxid has not been broadcast yet - result = rpc.rewardsunlock(plan_name, fundingtxid, locktxid) - assert_error(result) - - # broadcast xtn - txid = rpc.sendrawtransaction(locktxid) - assert txid, 'got txid from sendrawtransaction' - - # confirm the xtn above - wait_some_blocks(rpc, 1) - - # will not unlock since reward amount is less than tx fee - result = rpc.rewardsunlock(plan_name, fundingtxid, locktxid) - assert_error(result) +import time +from lib.pytest_util import validate_template, mine_and_waitconfirms, validate_raddr_pattern, \ + randomstring, randomhex + + +@pytest.mark.usefixtures("proxy_connection", "test_params") +class TestRewardsCC: + + def test_rewardscreatefunding(self, rewards_plan): + createfunding_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc = rewards_plan.rpc[0] + rewards_plan.new_rewardsplan(rpc, schema=createfunding_schema) + + def test_rewardsaddress(self, rewards_plan): + rewardsaddress_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'error': {'type': 'string'}, + 'RewardsCCAddress': {'type': 'string'}, + 'RewardsCCBalance': {'type': 'number'}, + 'RewardsNormalAddress': {'type': 'string'}, + 'RewardsNormalBalance': {'type': 'number'}, + 'RewardsCCTokensAddress': {'type': 'string'}, + 'PubkeyCCaddress(Rewards)': {'type': 'string'}, + 'PubkeyCCbalance(Rewards)': {'type': 'number'}, + 'myCCAddress(Rewards)': {'type': 'string'}, + 'myCCbalance(Rewards)': {'type': 'number'}, + 'myaddress': {'type': 'string'}, + 'mybalance': {'type': 'number'} + }, + 'required': ['result'] + } + + rpc = rewards_plan.rpc[0] + pubkey = rewards_plan.pubkey[0] + res = rpc.rewardsaddress() + validate_template(res, rewardsaddress_schema) + assert res.get('result') == 'success' + + res = rpc.rewardsaddress() + for key in res.keys(): + if key.find('ddress') > 0: + assert validate_raddr_pattern(res.get(key)) + + res = rpc.rewardsaddress(pubkey) + for key in res.keys(): + if key.find('ddress') > 0: + assert validate_raddr_pattern(res.get(key)) + + def test_rewarsdlist(self, rewards_plan): + rewadslist_schema = { + 'type': 'array', + 'items': {'type': 'string'} + } + + rpc = rewards_plan.rpc[0] + res = rpc.rewardslist() + validate_template(res, rewadslist_schema) + + def test_rewardsinfo(self, rewards_plan): + rewardsinfo_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'error': {'type': 'string'}, + 'fundingtxid': {'type': 'string'}, + 'name': {'type': 'string'}, + 'sbits': {'type': 'integer'}, + 'APR': {'type': 'string'}, + 'minseconds': {'type': 'integer'}, + 'maxseconds': {'type': 'integer'}, + 'mindeposit': {'type': 'string'}, + 'funding': {'type': 'string'}, + 'locked': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc = rewards_plan.rpc[0] + pubkey = rewards_plan.pubkey[1] + if not rewards_plan.base_plan: + rewards_plan.new_rewardsplan(rpc, pubkey) + rewards_plan.rewardsinfo_maincheck(rpc, rewards_plan.base_plan.get('fundingtxid'), rewardsinfo_schema) + + def test_rewardsaddfunding(self, rewards_plan): + addfunding_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc = rewards_plan.rpc[0] + pubkey = rewards_plan.pubkey[1] + if not rewards_plan.base_plan: + rewards_plan.new_rewardsplan(rpc, pubkey) + rewards_plan.rewardsaddfunding_maincheck(rpc, rewards_plan.base_plan.get('fundingtxid'), addfunding_schema) + + def test_lock_unlock(self, rewards_plan): + lock_unlock_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc = rewards_plan.rpc[0] + pubkey = rewards_plan.pubkey[1] + if not rewards_plan.base_plan: + rewards_plan.new_rewardsplan(rpc, pubkey) + rewards_plan.un_lock_maincheck(rpc, rewards_plan.base_plan.get('fundingtxid'), lock_unlock_schema) + + +@pytest.mark.usefixtures("proxy_connection", "test_params") +class TestRewardsCCExtras: + + def test_bad_calls(self, rewards_plan): + rpc = rewards_plan.rpc[0] + pubkey = rewards_plan.pubkey[1] + if not rewards_plan.base_plan: + rewards_plan.new_rewardsplan(rpc, pubkey) + fundtxid = rewards_plan.base_plan.get('fundingtxid') + + name = rpc.rewardsinfo(fundtxid).get('name') + invalidfunding = randomhex() + # looking up non-existent reward should return error + res = rpc.rewardsinfo(invalidfunding) + assert res.get('result') == 'error' + + # creating rewards plan with name > 8 chars, should return error + res = rpc.rewardscreatefunding("STUFFSTUFF", "7777", "25", "0", "10", "10") + assert res.get('result') == 'error' + + # creating rewards plan with 0 funding + res = rpc.rewardscreatefunding("STUFF", "0", "25", "0", "10", "10") + assert res.get('result') == 'error' + + # creating rewards plan with 0 maxdays + res = rpc.rewardscreatefunding("STUFF", "7777", "25", "0", "10", "0") + assert res.get('result') == 'error' + + # creating rewards plan with > 25% APR + res = rpc.rewardscreatefunding("STUFF", "7777", "30", "0", "10", "10") + assert res.get('result') == 'error' + + # creating reward plan with already existing name, should return error + res = rpc.rewardscreatefunding(name, "777", "25", "0", "10", "10") + assert res.get('result') == 'error' + + # add funding amount must be positive + res = rpc.rewardsaddfunding(name, fundtxid, "-1") + assert res.get('result') == 'error' + + # add funding amount must be positive + res = rpc.rewardsaddfunding(name, fundtxid, "0") + assert res.get('result') == 'error' + + # trying to lock funds, locking funds amount must be positive + res = rpc.rewardslock(name, fundtxid, "-5") + assert res.get('result') == 'error' + + # trying to lock funds, locking funds amount must be positive + res = rpc.rewardslock(name, fundtxid, "0") + assert res.get('result') == 'error' + + # trying to lock less than the min amount is an error + res = rpc.rewardslock(name, fundtxid, "7") + assert res.get('result') == 'error' diff --git a/qa/pytest_komodo/cc_modules/test_token.py b/qa/pytest_komodo/cc_modules/test_token.py index a1642cc306c..64e0a0bceca 100644 --- a/qa/pytest_komodo/cc_modules/test_token.py +++ b/qa/pytest_komodo/cc_modules/test_token.py @@ -1,254 +1,296 @@ #!/usr/bin/env python3 -# Copyright (c) 2019 SuperNET developers +# Copyright (c) 2021 SuperNET developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. import pytest -import time - -from util import assert_success, assert_error, check_if_mined,\ - send_and_mine, rpc_connect, wait_some_blocks, komodo_teardown - - -@pytest.mark.usefixtures("proxy_connection") -def test_token(test_params): - - # test params inits - rpc = test_params.get('node1').get('rpc') - rpc1 = test_params.get('node2').get('rpc') - - pubkey = test_params.get('node1').get('pubkey') - pubkey1 = test_params.get('node2').get('pubkey') - - is_fresh_chain = test_params.get("is_fresh_chain") - - result = rpc.tokenaddress() - assert_success(result) - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - result = rpc.tokenaddress(pubkey) - assert_success(result) - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - result = rpc.assetsaddress() - assert_success(result) - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - result = rpc.assetsaddress(pubkey) - assert_success(result) - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - # there are no tokens created yet - # TODO: this test conflicts with heir test because token creating for heir -# if is_fresh_chain: -# result = rpc.tokenlist() -# assert result == [] - - # trying to create token with negative supply - result = rpc.tokencreate("NUKE", "-1987420", "no bueno supply") - assert_error(result) - - # creating token with name more than 32 chars - result = rpc.tokencreate("NUKE123456789012345678901234567890", "1987420", "name too long") - assert_error(result) - - # creating valid token - result = rpc.tokencreate("DUKE", "1987.420", "Duke's custom token") - assert_success(result) - - tokenid = send_and_mine(result['hex'], rpc) - - result = rpc.tokenlist() - assert tokenid in result - - # there are no token orders yet - if is_fresh_chain: - result = rpc.tokenorders(tokenid) - assert result == [] - - # getting token balance for non existing tokenid - result = rpc.tokenbalance(pubkey) - assert_error(result) - - # get token balance for token with pubkey - result = rpc.tokenbalance(tokenid, pubkey) - assert_success(result) - assert result['balance'] == 198742000000 - assert result['tokenid'] == tokenid - - # get token balance for token without pubkey - result = rpc.tokenbalance(tokenid) - assert_success(result) - assert result['balance'] == 198742000000 - assert result['tokenid'] == tokenid - - # this is not a valid assetid - result = rpc.tokeninfo(pubkey) - assert_error(result) - - # check tokeninfo for valid token - result = rpc.tokeninfo(tokenid) - assert_success(result) - assert result['tokenid'] == tokenid - assert result['owner'] == pubkey - assert result['name'] == "DUKE" - assert result['supply'] == 198742000000 - assert result['description'] == "Duke's custom token" - - # invalid numtokens ask - result = rpc.tokenask("-1", tokenid, "1") - assert_error(result) - - # invalid numtokens ask - result = rpc.tokenask("0", tokenid, "1") - assert_error(result) - - # invalid price ask - result = rpc.tokenask("1", tokenid, "-1") - assert_error(result) - - # invalid price ask - result = rpc.tokenask("1", tokenid, "0") - assert_error(result) - - # invalid tokenid ask - result = rpc.tokenask("100", "deadbeef", "1") - assert_error(result) - - # valid ask - tokenask = rpc.tokenask("100", tokenid, "7.77") - tokenaskhex = tokenask['hex'] - tokenaskid = send_and_mine(tokenask['hex'], rpc) - result = rpc.tokenorders(tokenid) - order = result[0] - assert order, "found order" - - # invalid ask fillunits - result = rpc.tokenfillask(tokenid, tokenaskid, "0") - assert_error(result) - - # invalid ask fillunits - result = rpc.tokenfillask(tokenid, tokenaskid, "-777") - assert_error(result) - - # valid ask fillunits - fillask = rpc.tokenfillask(tokenid, tokenaskid, "777") - result = send_and_mine(fillask['hex'], rpc) - txid = result[0] - assert txid, "found txid" - - # should be no token orders - result = rpc.tokenorders(tokenid) - assert result == [] - - # checking ask cancellation - testorder = rpc.tokenask("100", tokenid, "7.77") - testorderid = send_and_mine(testorder['hex'], rpc) - # from other node (ensuring that second node have enough balance to cover txfee - # to get the actual error - not "not enough balance" one - rpc.sendtoaddress(rpc1.getnewaddress(), 1) - time.sleep(10) # to ensure transactions are in different blocks - rpc.sendtoaddress(rpc1.getnewaddress(), 1) - wait_some_blocks(rpc, 2) - result = rpc1.getbalance() - assert result > 0.1 - - result = rpc1.tokencancelask(tokenid, testorderid) - assert_error(result) - - # from valid node - cancel = rpc.tokencancelask(tokenid, testorderid) - send_and_mine(cancel["hex"], rpc) - - # TODO: should be no ask in orders - bad test - if is_fresh_chain: - result = rpc.tokenorders(tokenid) - assert result == [] - - # invalid numtokens bid - result = rpc.tokenbid("-1", tokenid, "1") - assert_error(result) - - # invalid numtokens bid - result = rpc.tokenbid("0", tokenid, "1") - assert_error(result) - - # invalid price bid - result = rpc.tokenbid("1", tokenid, "-1") - assert_error(result) - - # invalid price bid - result = rpc.tokenbid("1", tokenid, "0") - assert_error(result) - - # invalid tokenid bid - result = rpc.tokenbid("100", "deadbeef", "1") - assert_error(result) - - tokenbid = rpc.tokenbid("100", tokenid, "10") - tokenbidhex = tokenbid['hex'] - tokenbidid = send_and_mine(tokenbid['hex'], rpc) - result = rpc.tokenorders(tokenid) - order = result[0] - assert order, "found order" - - # invalid bid fillunits - result = rpc.tokenfillbid(tokenid, tokenbidid, "0") - assert_error(result) - - # invalid bid fillunits - result = rpc.tokenfillbid(tokenid, tokenbidid, "-777") - assert_error(result) - - # valid bid fillunits - fillbid = rpc.tokenfillbid(tokenid, tokenbidid, "1000") - result = send_and_mine(fillbid['hex'], rpc) - txid = result[0] - assert txid, "found txid" - - # should be no token orders - # TODO: should be no bid in orders - bad test - if is_fresh_chain: - result = rpc.tokenorders(tokenid) - assert result == [] - - # checking bid cancellation - testorder = rpc.tokenbid("100", tokenid, "7.77") - testorderid = send_and_mine(testorder['hex'], rpc) - - # from other node - result = rpc1.getbalance() - assert result > 0.1 - - result = rpc1.tokencancelbid(tokenid, testorderid) - #TODO: not throwing error now on tx generation - #assert_error(result) - - # from valid node - cancel = rpc.tokencancelbid(tokenid, testorderid) - send_and_mine(cancel["hex"], rpc) - result = rpc.tokenorders(tokenid) - assert result == [] - - # invalid token transfer amount (have to add status to CC code!) - randompubkey = "021a559101e355c907d9c553671044d619769a6e71d624f68bfec7d0afa6bd6a96" - result = rpc.tokentransfer(tokenid, randompubkey, "0") - assert_error(result) - - # invalid token transfer amount (have to add status to CC code!) - result = rpc.tokentransfer(tokenid, randompubkey, "-1") - assert_error(result) - - # valid token transfer - sendtokens = rpc.tokentransfer(tokenid, randompubkey, "1") - send_and_mine(sendtokens["hex"], rpc) - result = rpc.tokenbalance(tokenid, randompubkey) - assert result["balance"] == 1 +from slickrpc.exc import RpcException as RPCError +from lib.pytest_util import validate_template, mine_and_waitconfirms, randomstring, randomhex, validate_raddr_pattern + + +@pytest.mark.usefixtures("proxy_connection", "test_params") +class TestTokenCCcalls: + + def test_tokencreate_list_info(self, token_instance): + create_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + list_schema = { + 'type': 'array', + 'items': {'type': 'string'} + } + + info_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'tokenid': {'type': 'string'}, + 'owner': {'type': 'string'}, + 'name': {'type': 'string'}, + 'supply': {'type': 'integer'}, + 'description': {'type': 'string'}, + 'version': {'type': 'integer'}, + 'IsMixed': {'type': 'string'} + }, + 'required': ['result'] + } + + token_instance.new_token(token_instance.rpc[0], schema=create_schema) + + res = token_instance.rpc[0].tokenlist() + validate_template(res, list_schema) + + res = token_instance.rpc[0].tokeninfo(token_instance.base_token.get('tokenid')) + validate_template(res, info_schema) + + def test_tokenaddress(self, token_instance): + assetaddress_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + "GlobalPk Assets CC Address": {'type': 'string'}, + "GlobalPk Assets CC Balance": {'type': 'number'}, + "GlobalPk Assets Normal Address": {'type': 'string'}, + "GlobalPk Assets Normal Balance": {'type': 'number'}, + "GlobalPk Assets/Tokens CC Address": {'type': 'string'}, + "pubkey Assets CC Address": {'type': 'string'}, + "pubkey Assets CC Balance": {'type': 'number'}, + "mypk Assets CC Address": {'type': 'string'}, + "mypk Assets CC Balance": {'type': 'number'}, + "mypk Normal Address": {'type': 'string'}, + "mypk Normal Balance": {'type': 'number'} + }, + 'required': ['result'] + } + + tokenaddress_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + "GlobalPk Tokens CC Address": {'type': 'string'}, + "GlobalPk Tokens CC Balance": {'type': 'number'}, + "GlobalPk Tokens Normal Address": {'type': 'string'}, + "GlobalPk Tokens Normal Balance": {'type': 'number'}, + "pubkey Tokens CC Address": {'type': 'string'}, + "pubkey Tokens CC Balance": {'type': 'number'}, + "mypk Tokens CC Address": {'type': 'string'}, + "mypk Tokens CC Balance": {'type': 'number'}, + "mypk Normal Address": {'type': 'string'}, + "mypk Normal Balance": {'type': 'number'} + }, + 'required': ['result'] + } + + if not token_instance.base_token: + token_instance.new_token(token_instance.rpc[1]) + + res = token_instance.rpc[0].assetsaddress(token_instance.pubkey[0]) + validate_template(res, assetaddress_schema) + + res = token_instance.rpc[0].tokenaddress(token_instance.pubkey[0]) + validate_template(res, tokenaddress_schema) + + def test_tokentransfer_balance(self, token_instance): + transfer_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'} + }, + 'required': ['result'] + } + + balance_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'CCaddress': {'type': 'string'}, + 'tokenid': {'type': 'string'}, + 'balance': {'type': 'integer'} + }, + 'required': ['result'] + } + + if not token_instance.base_token: + token_instance.new_token(token_instance.rpc[1]) + + amount = 150 + res = token_instance.rpc[0].tokentransfer(token_instance.base_token.get('tokenid'), + token_instance.pubkey[1], str(amount)) + validate_template(res, transfer_schema) + txid = token_instance.rpc[0].sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, token_instance.rpc[0]) + + res = token_instance.rpc[1].tokenbalance(token_instance.base_token.get('tokenid'), + token_instance.pubkey[1]) + validate_template(res, balance_schema) + assert amount == res.get('balance') + assert token_instance.base_token.get('tokenid') == res.get('tokenid') + + def test_tokenask_bid_orders(self, token_instance): + askbid_schema = { + 'type': 'object', + 'properties': { + 'hex': {'type': 'string'} + }, + 'required': ['hex'] + } + + orders_schema = { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'funcid': {'type': 'string'}, + 'txid': {'type': 'string'}, + 'vout': {'type': 'integer'}, + 'amount': {'type': 'string'}, + 'askamount': {'type': 'string'}, + 'origaddress': {'type': 'string'}, + 'origtokenaddress': {'type': 'string'}, + 'tokenid': {'type': 'string'}, + 'totalrequired': {'type': ['string', 'integer']}, + 'price': {'type': 'string'} + } + } + } + + rpc1 = token_instance.rpc[0] + rpc2 = token_instance.rpc[1] + pubkey2 = token_instance.pubkey[1] + + if not token_instance.base_token: + token_instance.new_token(token_instance.rpc[1]) + amount1 = 150 + amount2 = 100 + price = 0.1 + + res = rpc1.tokenask(str(amount1), token_instance.base_token.get('tokenid'), str(price)) + validate_template(res, askbid_schema) + asktxid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(asktxid, rpc1) + + res = rpc1.tokenbid(str(amount2), token_instance.base_token.get('tokenid'), str(price)) + validate_template(res, askbid_schema) + bidtxid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(bidtxid, rpc1) + + # Check orders and myorders call + orders1 = rpc2.tokenorders(token_instance.base_token.get('tokenid')) + validate_template(orders1, orders_schema) + orders2 = rpc1.mytokenorders(token_instance.base_token.get('tokenid')) + validate_template(orders2, orders_schema) + # assert orders1 == orders2 + + # Check fills and cancel calls + res = rpc2.tokenfillask(token_instance.base_token.get('tokenid'), asktxid, str(int(amount1 * 0.5))) + validate_template(res, askbid_schema) + asktxid2 = rpc2.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(asktxid2, rpc2) + + res = rpc2.tokenfillbid(token_instance.base_token.get('tokenid'), bidtxid, str(int(amount2 * 0.5))) + validate_template(res, askbid_schema) + bidtxid2 = rpc2.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(bidtxid2, rpc2) + + res = rpc1.tokencancelask(token_instance.base_token.get('tokenid'), asktxid2) + validate_template(res, askbid_schema) + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + + res = rpc1.tokencancelbid(token_instance.base_token.get('tokenid'), bidtxid2) + validate_template(res, askbid_schema) + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + + # There should be no orders left after cancelling + orders = rpc1.mytokenorders(token_instance.base_token.get('tokenid')) + validate_template(orders, orders_schema) + assert len(orders) == 0 + + +@pytest.mark.usefixtures("proxy_connection", "test_params") +class TestTokenCC: + + def test_rewardsaddress(self, token_instance): + pubkey = token_instance.pubkey[0] + + res = token_instance.rpc[0].assetsaddress(pubkey) + for key in res.keys(): + if key.find('ddress') > 0: + assert validate_raddr_pattern(res.get(key)) + + res = token_instance.rpc[0].tokenaddress(pubkey) + for key in res.keys(): + if key.find('ddress') > 0: + assert validate_raddr_pattern(res.get(key)) + + def test_bad_calls(self, token_instance): + if not token_instance.base_token: + token_instance.new_token(token_instance.rpc[1]) + + rpc = token_instance.rpc[0] + pubkey = token_instance.pubkey[0] + + name = token_instance.base_token.get('name') + tokenid = token_instance.base_token.get('tokenid') + + # trying to create token with negative supply + with pytest.raises(RPCError): + res = rpc.tokencreate("NUKE", "-1987420", "no bueno supply") + assert res.get('error') + # creating token with name more than 32 chars + res = rpc.tokencreate("NUKE123456789012345678901234567890", "1987420", "name too long") + assert res.get('error') + # getting token balance for non existing tokenid + res = rpc.tokenbalance("", pubkey) + assert res.get('error') + # no info for invalid tokenid + res = rpc.tokeninfo(pubkey) + assert res.get('error') + # invalid token transfer amount + randompubkey = randomhex() + res = rpc.tokentransfer(tokenid, randompubkey, "0") + assert res.get('error') + # invalid token transfer amount + res = rpc.tokentransfer(tokenid, randompubkey, "-1") + assert res.get('error') + # invalid numtokens bid + res = rpc.tokenbid("-1", tokenid, "1") + assert res.get('error') + # invalid numtokens bid + res = rpc.tokenbid("0", tokenid, "1") + assert res.get('error') + # invalid price bid + with pytest.raises(RPCError): + res = rpc.tokenbid("1", tokenid, "-1") + assert res.get('error') + # invalid price bid + res = rpc.tokenbid("1", tokenid, "0") + assert res.get('error') + # invalid tokenid bid + res = rpc.tokenbid("100", "deadbeef", "1") + assert res.get('error') + # invalid numtokens ask + res = rpc.tokenask("-1", tokenid, "1") + assert res.get('error') + # invalid numtokens ask + res = rpc.tokenask("0", tokenid, "1") + assert res.get('error') + # invalid price ask + with pytest.raises(RPCError): + res = rpc.tokenask("1", tokenid, "-1") + assert res.get('error') + # invalid price ask + res = rpc.tokenask("1", tokenid, "0") + assert res.get('error') + # invalid tokenid ask + res = rpc.tokenask("100", "deadbeef", "1") + assert res.get('error') diff --git a/qa/pytest_komodo/cc_modules/test_tokenv2.py b/qa/pytest_komodo/cc_modules/test_tokenv2.py new file mode 100644 index 00000000000..b42d9ab2bcc --- /dev/null +++ b/qa/pytest_komodo/cc_modules/test_tokenv2.py @@ -0,0 +1,314 @@ +#!/usr/bin/env python3 +# Copyright (c) 2021 SuperNET developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php. + +import pytest +from slickrpc.exc import RpcException as RPCError +from lib.pytest_util import validate_template, mine_and_waitconfirms, randomstring, randomhex, validate_raddr_pattern + + +@pytest.mark.usefixtures("proxy_connection") +class TestTokenCCv2Calls: + + @staticmethod + def new_token(proxy, schema=None): + name = randomstring(8) + amount = '0.10000000' + res = proxy.tokenv2create(name, amount, "test token 1") + if schema: + validate_template(res, schema) + assert res.get('result') == 'success' + txid = proxy.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, proxy) + token = { + 'tokenid': txid, + 'name': name + } + return token + + def test_tokenv2create_v2list_v2info(self, test_params): + v2create_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'error': {'type': 'string'} + }, + 'required': ['result'] + } + + v2list_schema = { + 'type': 'array', + 'items': {'type': 'string'} + } + + v2info_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'tokenid': {'type': 'string'}, + 'owner': {'type': 'string'}, + 'name': {'type': 'string'}, + 'supply': {'type': 'integer'}, + 'description': {'type': 'string'}, + 'version': {'type': 'integer'}, + 'IsMixed': {'type': 'string'} + }, + 'required': ['result'] + } + + rpc = test_params.get('node1').get('rpc') + token = self.new_token(rpc, schema=v2create_schema) + + res = rpc.tokenv2list() + validate_template(res, v2list_schema) + + res = rpc.tokenv2info(token.get('tokenid')) + validate_template(res, v2info_schema) + + def test_tokenv2address(self, test_params): + v2assetaddress_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + "GlobalPk Assetsv2 CC Address": {'type': 'string'}, + "GlobalPk Assetsv2 CC Balance": {'type': 'number'}, + "GlobalPk Assetsv2 Normal Address": {'type': 'string'}, + "GlobalPk Assetsv2 Normal Balance": {'type': 'number'}, + "GlobalPk Assetsv2/Tokens CC Address": {'type': 'string'}, + "pubkey Assetsv2 CC Address": {'type': 'string'}, + "pubkey Assetsv2 CC Balance": {'type': 'number'}, + "mypk Assetsv2 CC Address": {'type': 'string'}, + "mypk Assetsv2 CC Balance": {'type': 'number'}, + "mypk Normal Address": {'type': 'string'}, + "mypk Normal Balance": {'type': 'number'} + }, + 'required': ['result'] + } + + v2tokenaddress_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + "GlobalPk Tokensv2 CC Address": {'type': 'string'}, + "GlobalPk Tokensv2 CC Balance": {'type': 'number'}, + "GlobalPk Tokensv2 Normal Address": {'type': 'string'}, + "GlobalPk Tokensv2 Normal Balance": {'type': 'number'}, + "pubkey Tokensv2 CC Address": {'type': 'string'}, + "pubkey Tokensv2 CC Balance": {'type': 'number'}, + "mypk Tokensv2 CC Address": {'type': 'string'}, + "mypk Tokensv2 CC Balance": {'type': 'number'}, + "mypk Normal Address": {'type': 'string'}, + "mypk Normal Balance": {'type': 'number'} + }, + 'required': ['result'] + } + + rpc = test_params.get('node1').get('rpc') + pubkey = test_params.get('node1').get('pubkey') + + res = rpc.assetsv2address(pubkey) + validate_template(res, v2assetaddress_schema) + + res = rpc.tokenv2address(pubkey) + validate_template(res, v2tokenaddress_schema) + + def test_tokenv2transfer_v2balance(self, test_params): + v2transfer_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'hex': {'type': 'string'} + }, + 'required': ['result'] + } + + v2balance_schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'CCaddress': {'type': 'string'}, + 'tokenid': {'type': 'string'}, + 'balance': {'type': 'integer'} + }, + 'required': ['result'] + } + + rpc1 = test_params.get('node1').get('rpc') + rpc2 = test_params.get('node2').get('rpc') + pubkey2 = test_params.get('node2').get('pubkey') + + token1 = self.new_token(rpc1) + + amount = 150 + res = rpc1.tokenv2transfer(token1.get('tokenid'), pubkey2, str(amount)) + validate_template(res, v2transfer_schema) + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + + res = rpc2.tokenv2balance(token1.get('tokenid'), pubkey2) + validate_template(res, v2balance_schema) + assert amount == res.get('balance') + assert token1.get('tokenid') == res.get('tokenid') + + def test_tokenv2ask_v2bid_v2orders(self, test_params): + v2askbid_schema = { + 'type': 'object', + 'properties': { + 'hex': {'type': 'string'} + }, + 'required': ['hex'] + } + + v2orders_schema = { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'funcid': {'type': 'string'}, + 'txid': {'type': 'string'}, + 'vout': {'type': 'integer'}, + 'amount': {'type': 'string'}, + 'askamount': {'type': 'string'}, + 'origaddress': {'type': 'string'}, + 'origtokenaddress': {'type': 'string'}, + 'tokenid': {'type': 'string'}, + 'totalrequired': {'type': ['string', 'integer']}, + 'price': {'type': ['integer', 'number']} + } + } + } + + rpc1 = test_params.get('node1').get('rpc') + rpc2 = test_params.get('node2').get('rpc') + pubkey2 = test_params.get('node2').get('pubkey') + + token1 = self.new_token(rpc1) + amount1 = 150 + amount2 = 100 + price = 0.1 + + res = rpc1.tokenv2ask(str(amount1), token1.get('tokenid'), price) + validate_template(res, v2askbid_schema) + asktxid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(asktxid, rpc1) + + res = rpc1.tokenv2bid(str(amount2), token1.get('tokenid'), price) + validate_template(res, v2askbid_schema) + bidtxid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(bidtxid, rpc1) + + # Check orders and myorders call + orders1 = rpc2.tokenv2orders(token1.get('tokenid')) + validate_template(orders1, v2orders_schema) + orders2 = rpc1.mytokenv2orders(token1.get('tokenid')) + validate_template(orders2, v2orders_schema) + assert orders1 == orders2 + + # Check fills and cancel calls + res = rpc2.tokenv2fillask(token1.get('tokenid'), asktxid, str(int(amount1 * 0.5))) + validate_template(res, v2askbid_schema) + asktxid2 = rpc2.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(asktxid2, rpc2) + + res = rpc2.tokenv2fillbid(token1.get('tokenid'), bidtxid, str(int(amount2 * 0.5))) + validate_template(res, v2askbid_schema) + bidtxid2 = rpc2.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(bidtxid2, rpc2) + + res = rpc1.tokenv2cancelask(token1.get('tokenid'), asktxid2) + validate_template(res, v2askbid_schema) + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + + res = rpc1.tokenv2cancelbid(token1.get('tokenid'), bidtxid2) + validate_template(res, v2askbid_schema) + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + + # There should be no orders left after cancelling + orders = rpc1.mytokenv2orders(token1.get('tokenid')) + validate_template(orders, v2orders_schema) + assert len(orders) == 0 + + +@pytest.mark.usefixtures("proxy_connection") +class TestTokenCCv2: + + def test_rewardsaddress(self, test_params): + rpc = test_params.get('node1').get('rpc') + pubkey = test_params.get('node1').get('pubkey') + + res = rpc.assetsv2address(pubkey) + for key in res.keys(): + if key.find('ddress') > 0: + assert validate_raddr_pattern(res.get(key)) + + res = rpc.tokenv2address(pubkey) + for key in res.keys(): + if key.find('ddress') > 0: + assert validate_raddr_pattern(res.get(key)) + + @staticmethod + def bad_calls(proxy, token, pubkey): + name = token.get('name') + tokenid = token.get('tokenid') + # trying to create token with negative supply + with pytest.raises(RPCError): + res = proxy.tokenv2create("NUKE", "-1987420", "no bueno supply") + assert res.get('error') + # creating token with name more than 32 chars + res = proxy.tokenv2create("NUKE123456789012345678901234567890", "1987420", "name too long") + assert res.get('error') + # getting token balance for non existing tokenid + res = proxy.tokenv2balance("", pubkey) + assert res.get('error') + # no info for invalid tokenid + res = proxy.tokenv2info(pubkey) + assert res.get('error') + # invalid token transfer amount + randompubkey = randomhex() + res = proxy.tokenv2transfer(tokenid, randompubkey, "0") + assert res.get('error') + # invalid token transfer amount + res = proxy.tokenv2transfer(tokenid, randompubkey, "-1") + assert res.get('error') + # invalid numtokens bid + res = proxy.tokenv2bid("-1", tokenid, "1") + assert res.get('error') + # invalid numtokens bid + res = proxy.tokenv2bid("0", tokenid, "1") + assert res.get('error') + # invalid price bid + with pytest.raises(RPCError): + res = proxy.tokenv2bid("1", tokenid, "-1") + assert res.get('error') + # invalid price bid + res = proxy.tokenv2bid("1", tokenid, "0") + assert res.get('error') + # invalid tokenid bid + res = proxy.tokenv2bid("100", "deadbeef", "1") + assert res.get('error') + # invalid numtokens ask + res = proxy.tokenv2ask("-1", tokenid, "1") + assert res.get('error') + # invalid numtokens ask + res = proxy.tokenv2ask("0", tokenid, "1") + assert res.get('error') + # invalid price ask + with pytest.raises(RPCError): + res = proxy.tokenv2ask("1", tokenid, "-1") + assert res.get('error') + # invalid price ask + res = proxy.tokenv2ask("1", tokenid, "0") + assert res.get('error') + # invalid tokenid ask + res = proxy.tokenv2ask("100", "deadbeef", "1") + assert res.get('error') + + def test_bad_calls(self, test_params): + rpc = test_params.get('node1').get('rpc') + pubkey = test_params.get('node1').get('pubkey') + token = TestTokenCCv2Calls.new_token(rpc) + self.bad_calls(rpc, token, pubkey) diff --git a/qa/pytest_komodo/cc_modules/test_unspentccundex.py b/qa/pytest_komodo/cc_modules/test_unspentccundex.py new file mode 100644 index 00000000000..139fbe19c64 --- /dev/null +++ b/qa/pytest_komodo/cc_modules/test_unspentccundex.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +# Copyright (c) 2020 SuperNET developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php. + +# this is a test to check a new index for unspent cc utxos activated with -unspentccindex + +import pytest +import time +from slickrpc.exc import RpcException as RPCError +from lib.util import assert_success, assert_error, mine_and_waitconfirms,\ + send_and_mine, rpc_connect, wait_some_blocks, komodo_teardown + + +@pytest.mark.usefixtures("proxy_connection") +def test_ccindex(test_params): + + # test params inits + rpc = test_params.get('node1').get('rpc') + rpc1 = test_params.get('node2').get('rpc') + + pubkey = test_params.get('node1').get('pubkey') + pubkey1 = test_params.get('node2').get('pubkey') + + is_fresh_chain = test_params.get("is_fresh_chain") + + result = rpc.tokenaddress() + assert_success(result) + for x in result.keys(): + if x.find('ddress') > 0: + assert result[x][0] == 'R' + + # get token cc address for pubkey: + result = rpc.tokenaddress(pubkey) + assert_success(result) + pubkeyTokenCCAddress = "" + for x in result.keys(): + if x.find('ddress') > 0: + assert result[x][0] == 'R' + if x == 'pubkey Tokens CC Address': + pubkeyTokenCCAddress = result[x] + + # get token cc address for pubkey1: + result = rpc.tokenaddress(pubkey1) + assert_success(result) + pubkey1TokenCCAddress = "" + for x in result.keys(): + if x.find('ddress') > 0: + assert result[x][0] == 'R' + if x == 'pubkey Tokens CC Address': + pubkey1TokenCCAddress = result[x] + + # there are no tokens created yet + # TODO: this test conflicts with heir test because token creating for heir +# if is_fresh_chain: +# result = rpc.tokenlist() +# assert result == [] + + print("stop mining to test txns in mempool") + rpc.setgenerate(False) + rpc1.setgenerate(False) + + print("creating test token...") + result = rpc.tokencreate("T1", "20", "token for testing cc index") + assert_success(result) + + tokenid = rpc.sendrawtransaction(result['hex']) + + # check mempool index: + print("check cc index for tokencreate in mempool...") + + # check one utxo in the index + result = rpc.listccunspents(pubkeyTokenCCAddress, tokenid) + # print('type(result)=' + str(type(result))) + assert(str(type(result)) == "") + assert(len(result) == 1) + assert(result[0]['creationId'] == tokenid) + assert(result[0]['txhash'] == tokenid) + assert(result[0]['satoshis'] == 20*100000000) + assert(result[0]['funcid'].upper() == "C") + assert(result[0]['blockHeight'] == 0) # in mempool + + print("check cc index for tokentransfer in mempool...") + + result = rpc.tokentransfer(tokenid, pubkey1, "1") + assert_success(result) + txid = rpc.sendrawtransaction(result['hex']) + + # check two utxos in the mempool index + + result = rpc.listccunspents(pubkeyTokenCCAddress, tokenid) + assert(str(type(result)) == "") + + # note: once I got assert failed here: + # 'E assert 0 == 1' + # probably it happened because setgenerate(False) had not finished atm + assert(len(result) == 1) + assert(result[0]['creationId'] == tokenid) + assert(result[0]['txhash'] == txid) + assert(result[0]['satoshis'] == 20*100000000-1) + assert(result[0]['funcid'].upper() == "T") + assert(result[0]['blockHeight'] == 0) # in mempool + + result = rpc.listccunspents(pubkey1TokenCCAddress, tokenid) + assert(str(type(result)) == "") + assert(len(result) == 1) + assert(result[0]['creationId'] == tokenid) + assert(result[0]['txhash'] == txid) + assert(result[0]['satoshis'] == 1) + assert(result[0]['funcid'].upper() == "T") + assert(result[0]['blockHeight'] == 0) # in mempool + + print("mine txns and check cc index in db...") + + rpc.setgenerate(True, 1) + while True: + print("waiting until mempool empty...") + time.sleep(10) + mempool = rpc.getrawmempool() + if len(mempool) == 0: + break + + result = rpc.listccunspents(pubkeyTokenCCAddress, tokenid) + assert(str(type(result)) == "") + assert(len(result) == 1) + assert(result[0]['creationId'] == tokenid) + assert(result[0]['txhash'] == txid) + assert(result[0]['satoshis'] == 20*100000000-1) + assert(result[0]['funcid'].upper() == "T") + assert(result[0]['blockHeight'] != 0) # not in mempool + + result = rpc.listccunspents(pubkey1TokenCCAddress, tokenid) + assert(str(type(result)) == "") + assert(len(result) == 1) + assert(result[0]['creationId'] == tokenid) + assert(result[0]['txhash'] == txid) + assert(result[0]['satoshis'] == 1) + assert(result[0]['funcid'].upper() == "T") + assert(result[0]['blockHeight'] != 0) # not in mempool + + print("test cc index okay") + diff --git a/qa/pytest_komodo/chainconfig.json b/qa/pytest_komodo/chainconfig.json index 7fea510b364..faff3c9ee50 100644 --- a/qa/pytest_komodo/chainconfig.json +++ b/qa/pytest_komodo/chainconfig.json @@ -2,14 +2,15 @@ "TONYCI": { "rpc_user": "test", "rpcpassword": "test", - "rpcallowip": "127.0.0.1", + "rpcallowip": "0.0.0.0/0", "rpcport": 7000, "port": 6000, - "rpcbind": "127.0.0.1", + "rpcbind": "0.0.0.0", "ac_name": "TONYCI", "ac_reward": "100000000000", "ac_supply": "10000000000", - "ac_cc": "2" + "ac_cc": "2", + "ac_blocktime": "30" }, "HUSH3": { "rpc_user": "test", diff --git a/qa/pytest_komodo/chainstart.py b/qa/pytest_komodo/chainstart.py index eeebb6cf350..948cb299fcf 100644 --- a/qa/pytest_komodo/chainstart.py +++ b/qa/pytest_komodo/chainstart.py @@ -4,7 +4,7 @@ import subprocess import wget import tarfile -from basic.pytest_util import create_proxy, validate_proxy, enable_mining +from lib.pytest_util import create_proxy, validate_proxy, enable_mining def load_env_config(): diff --git a/qa/pytest_komodo/ci_cleanup.sh b/qa/pytest_komodo/ci_cleanup.sh deleted file mode 100755 index a15baf38427..00000000000 --- a/qa/pytest_komodo/ci_cleanup.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -rm -Rf node_0 -rm -Rf node_1 -rm -Rf __pycache__/ -rm TONYCI_7776 diff --git a/qa/pytest_komodo/ci_set_dex.sh b/qa/pytest_komodo/ci_set_dex.sh index 644d5025c18..c620f1b4c89 100755 --- a/qa/pytest_komodo/ci_set_dex.sh +++ b/qa/pytest_komodo/ci_set_dex.sh @@ -3,18 +3,18 @@ # chains start script params export CLIENTS=2 export CHAIN="TONYCI" -export TEST_ADDY0="RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd" -export TEST_WIF0="UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN" -export TEST_PUBKEY0="02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7" +export TEST_ADDY0="RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein" +export TEST_WIF0="UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr" +export TEST_PUBKEY0="02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9" export TEST_ADDY1="RHoTHYiHD8TU4k9rbY4Aoj3ztxUARMJikH" export TEST_WIF1="UwmmwgfXwZ673brawUarPzbtiqjsCPWnG311ZRAL4iUCZLBLYeDu" export TEST_PUBKEY1="0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149" -export TEST_ADDY2="RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein" -export TEST_WIF2="UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr" -export TEST_PUBKEY2="02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9" +export TEST_ADDY2="RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd" +export TEST_WIF2="UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN" +export TEST_PUBKEY2="02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7" export CHAIN_MODE="DEX2" export IS_BOOTSTRAP_NEEDED="True" -export BOOTSTRAP_URL="https://sirseven.me/share/bootstrap.tar.gz" +export BOOTSTRAP_URL="https://sirseven.me/share/bootstrap4.tar.gz" # starting the chains python3 chainstart.py diff --git a/qa/pytest_komodo/ci_setup.sh b/qa/pytest_komodo/ci_setup.sh index 0fb5807a960..72939bde3ca 100755 --- a/qa/pytest_komodo/ci_setup.sh +++ b/qa/pytest_komodo/ci_setup.sh @@ -3,15 +3,15 @@ # chains start script params export CLIENTS=2 export CHAIN="TONYCI" -export TEST_ADDY0="RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd" -export TEST_WIF0="UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN" -export TEST_PUBKEY0="02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7" +export TEST_ADDY0="RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein" +export TEST_WIF0="UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr" +export TEST_PUBKEY0="02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9" export TEST_ADDY1="RHoTHYiHD8TU4k9rbY4Aoj3ztxUARMJikH" export TEST_WIF1="UwmmwgfXwZ673brawUarPzbtiqjsCPWnG311ZRAL4iUCZLBLYeDu" export TEST_PUBKEY1="0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149" export CHAIN_MODE="REGULAR" export IS_BOOTSTRAP_NEEDED="True" -export BOOTSTRAP_URL="https://sirseven.me/share/bootstrap.tar.gz" +export BOOTSTRAP_URL="https://sirseven.me/share/bootstrap4.tar.gz" # starting the chains python3 chainstart.py diff --git a/qa/pytest_komodo/conftest.py b/qa/pytest_komodo/conftest.py index a1392e78612..a98a46f962e 100644 --- a/qa/pytest_komodo/conftest.py +++ b/qa/pytest_komodo/conftest.py @@ -2,11 +2,8 @@ import json import os import time -# Using different proxy to bypass libcurl issues on Windows -try: - from slickrpc import Proxy -except ImportError: - from bitcoinrpc.authproxy import AuthServiceProxy as Proxy +from lib.pytest_util import OraclesCC, TokenCC, DiceCC, ChannelsCC, RewardsCC +from slickrpc import Proxy @pytest.fixture(scope='session') @@ -54,4 +51,34 @@ def test_params(proxy_connection): rpc = proxy_connection(node_params) test_params.update({node: node_params}) test_params[node].update({'rpc': rpc}) - return test_params \ No newline at end of file + return test_params + + +@pytest.fixture(scope='session') +def oracle_instance(test_params): + oracle = OraclesCC(test_params) + return oracle + + +@pytest.fixture(scope='session') +def token_instance(test_params): + token = TokenCC(test_params) + return token + + +@pytest.fixture(scope='session') +def dice_casino(test_params): + dice = DiceCC(test_params) + return dice + + +@pytest.fixture(scope='session') +def channel_instance(test_params): + channel = ChannelsCC(test_params) + return channel + + +@pytest.fixture(scope='session') +def rewards_plan(test_params): + rewards_plan = RewardsCC(test_params) + return rewards_plan diff --git a/qa/pytest_komodo/lib/__init__.py b/qa/pytest_komodo/lib/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/qa/pytest_komodo/lib/pytest_util.py b/qa/pytest_komodo/lib/pytest_util.py new file mode 100644 index 00000000000..dda063e752f --- /dev/null +++ b/qa/pytest_komodo/lib/pytest_util.py @@ -0,0 +1,565 @@ +import time +import jsonschema +import os +import random +import string +import hashlib +import re +import requests +from slickrpc import Proxy +from slickrpc.exc import RpcException as RPCError +from pycurl import error as HttpError + + +class CCInstance: + def __init__(self, test_params: dict): + """Base CC Instance class to wrap test_params data""" + self.rpc = [test_params.get(node).get('rpc') for node in test_params.keys()] + self.pubkey = [test_params.get(node).get('pubkey') for node in test_params.keys()] + self.address = [test_params.get(node).get('address') for node in test_params.keys()] + self.instance = None + + +class RewardsCC(CCInstance): + def __init__(self, test_params: dict): + super().__init__(test_params) + self.base_plan = None + + def new_rewardsplan(self, proxy, schema=None): + name = randomstring(4) + amount = '250' + apr = '25' + mindays = '0' + maxdays = '10' + mindeposit = '10' + res = proxy.rewardscreatefunding(name, amount, apr, mindays, maxdays, mindeposit) + if schema: + validate_template(res, schema) + assert res.get('result') == 'success' + txid = proxy.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, proxy) + rewardsplan = { + 'fundingtxid': txid, + 'name': name + } + if not self.base_plan: + self.base_plan = rewardsplan + return rewardsplan + + @staticmethod + def rewardsinfo_maincheck(proxy, fundtxid, schema): + res = proxy.rewardsinfo(fundtxid) + validate_template(res, schema) + assert res.get('result') == 'success' + + @staticmethod + def rewardsaddfunding_maincheck(proxy, fundtxid, schema): + name = proxy.rewardsinfo(fundtxid).get('name') + amount = proxy.rewardsinfo(fundtxid).get('mindeposit') # not related to mindeposit here, just to get amount + res = proxy.rewardsaddfunding(name, fundtxid, amount) + validate_template(res, schema) + assert res.get('result') == 'success' + txid = proxy.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, proxy) + + @staticmethod + def un_lock_maincheck(proxy, fundtxid, schema): + name = proxy.rewardsinfo(fundtxid).get('name') + amount = proxy.rewardsinfo(fundtxid).get('mindeposit') + res = proxy.rewardslock(name, fundtxid, amount) + validate_template(res, schema) + assert res.get('result') == 'success' + locktxid = proxy.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(locktxid, proxy) + print('\nWaiting some time to gain reward for locked funds') + time.sleep(10) + res = proxy.rewardsunlock(name, fundtxid, locktxid) + print(res) + validate_template(res, schema) + assert res.get('result') == 'error' # reward is less than txfee atm + + +class ChannelsCC(CCInstance): + def __init__(self, test_params: dict): + super().__init__(test_params) + self.base_channel = None + + def new_channel(self, proxy: object, destpubkey: str, numpayments='10', + paysize='100000', schema=None, tokenid=None) -> dict: + if tokenid: + res = proxy.channelsopen(destpubkey, numpayments, paysize, tokenid) + else: + res = proxy.channelsopen(destpubkey, numpayments, paysize) + if schema: + validate_template(res, schema) + open_txid = proxy.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(open_txid, proxy) + channel = { + 'open_txid': open_txid, + 'number_of_payments': numpayments, + } + if tokenid: + channel.update({'tokenid': tokenid}) + if not self.base_channel: + self.base_channel = channel + return channel + + @staticmethod + def channelslist_get(proxy: object, schema=None) -> str: + res = proxy.channelslist() + open_txid = None + if schema: + validate_template(res, schema) + # check dict items returned to find first available channel + for key in res.keys(): + if validate_tx_pattern(key): + open_txid = key + break + return open_txid + + +class OraclesCC(CCInstance): + def __init__(self, test_params: dict): + super().__init__(test_params) + self.base_oracle = None + + def new_oracle(self, proxy, schema=None, description="test oracle", o_type=None): + name = randomstring(8) + if not o_type: + o_type = "s" + res = proxy.oraclescreate(name, description, o_type) + elif isinstance(o_type, str): + res = proxy.oraclescreate(name, description, o_type) + elif isinstance(o_type, list): + txid = "" + oracles = [] + for single_o_type in o_type: + res = proxy.oraclescreate(name, description, single_o_type) + txid = proxy.sendrawtransaction(res.get('hex')) + oracles.append({ + 'format': single_o_type, + 'name': name, + 'description': description, + 'oracle_id': txid + }) + mine_and_waitconfirms(txid, proxy) + return oracles + else: + raise TypeError("Invalid oracles format: ", o_type) + if schema: + validate_template(res, schema) + assert res.get('result') == 'success' + txid = proxy.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, proxy) + oracle = { + 'format': o_type, + 'name': name, + 'description': description, + 'oracle_id': txid + } + if not self.base_oracle: + self.base_oracle = oracle + return oracle + + +class TokenCC(CCInstance): + def __init__(self, test_params: dict): + super().__init__(test_params) + self.base_token = None + + def new_token(self, proxy, schema=None): + name = randomstring(8) + amount = '0.10000000' + res = proxy.tokencreate(name, amount, "test token 1") + if schema: + validate_template(res, schema) + assert res.get('result') == 'success' + txid = proxy.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, proxy) + token = { + 'tokenid': txid, + 'name': name + } + if not self.base_token: + self.base_token = token + return token + + +class DiceCC(CCInstance): + def __init__(self, test_params: dict): + super().__init__(test_params) + self.open_casino = None + + def new_casino(self, proxy, schema=None): + rpc1 = proxy + name = randomstring(4) + funds = '777' + minbet = '1' + maxbet = '77' + maxodds = '10' + timeoutblocks = '5' + res = rpc1.dicefund(name, funds, minbet, maxbet, maxodds, timeoutblocks) + if schema: + validate_template(res, schema) + assert res.get('result') == 'success' + txid = rpc1.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(txid, rpc1) + casino = { + 'fundingtxid': txid, + 'name': name, + 'minbet': minbet, + 'maxbet': maxbet, + 'maxodds': maxodds + } + if not self.open_casino: + self.open_casino = casino + return casino + + @staticmethod + def diceinfo_maincheck(proxy, fundtxid, schema): + res = proxy.diceinfo(fundtxid) + validate_template(res, schema) + assert res.get('result') == 'success' + + @staticmethod + def diceaddfunds_maincheck(proxy, amount, fundtxid, schema): + name = proxy.diceinfo(fundtxid).get('name') + res = proxy.diceaddfunds(name, fundtxid, amount) + validate_template(res, schema) + assert res.get('result') == 'success' + addtxid = proxy.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(addtxid, proxy) + + @staticmethod + def dicebet_maincheck(proxy, casino, schema): + res = proxy.dicebet(casino.get('name'), casino.get('fundingtxid'), casino.get('minbet'), casino.get('maxodds')) + validate_template(res, schema) + assert res.get('result') == 'success' + bettxid = proxy.sendrawtransaction(res.get('hex')) + mine_and_waitconfirms(bettxid, proxy) + return bettxid + + @staticmethod + def dicestatus_maincheck(proxy, casino, bettx, schema): + res = proxy.dicestatus(casino.get('name'), casino.get('fundingtxid'), bettx) + validate_template(res, schema) + assert res.get('result') == 'success' + + @staticmethod + def dicefinsish_maincheck(proxy, casino, bettx, schema): + res = proxy.dicefinish(casino.get('name'), casino.get('fundingtxid'), bettx) + validate_template(res, schema) + assert res.get('result') == 'success' + + @staticmethod + def create_entropy(proxy, casino): + amount = '1' + for i in range(100): + res = proxy.diceaddfunds(casino.get('name'), casino.get('fundingtxid'), amount) + fhex = res.get('hex') + proxy.sendrawtransaction(fhex) + checkhex = proxy.diceaddfunds(casino.get('name'), casino.get('fundingtxid'), amount).get('hex') + tx = proxy.sendrawtransaction(checkhex) + mine_and_waitconfirms(tx, proxy) + + +def create_proxy(node_params_dictionary): + try: + proxy = Proxy("http://%s:%s@%s:%d" % (node_params_dictionary.get('rpc_user'), + node_params_dictionary.get('rpc_password'), + node_params_dictionary.get('rpc_ip'), + node_params_dictionary.get('rpc_port')), timeout=120) + except Exception as e: + raise Exception("Connection error! Probably no daemon on selected port. Error: ", e) + return proxy + + +def env_get(var, default): + try: + res = os.environ[var] + except KeyError: + res = default + return res + + +def get_chainstate(proxy): + vals = {} + res = proxy.getinfo() + vals.update({'synced': res.get('synced')}) + vals.update({'notarized': res.get('notarized')}) + vals.update({'blocks': res.get('blocks')}) + vals.update({'longestchain': res.get('longestchain')}) + return vals + + +def get_notary_stats(): + api = "https://komodostats.com/api/notary/summary.json" + local = "notary.json" + data = requests.get(api).json() + with open(local, 'w') as lf: + lf.write(str(data)) + return data + + +def check_notarized(proxy, api_stats, coin, blocktime=60): + maxblocksdiff = round(1500 / blocktime) + daemon_stats = proxy.getinfo() + notarizations = {} + for item in api_stats: + if item.get('ac_name') == coin: + notarizations = item + if not notarizations: + raise BaseException("Chain notary data not found") + if daemon_stats['notarized'] == notarizations['notarized']: + assert daemon_stats['notarizedhash'] == notarizations['notarizedhash'] + assert daemon_stats['notarizedtxid'] == notarizations['notarizedtxid'] + return True + elif abs(daemon_stats['notarazied'] - notarizations['notarized']) >= maxblocksdiff: + return False + else: + assert daemon_stats['notarized'] + assert daemon_stats['notarizedhash'] != '0000000000000000000000000000000000000000000000000000000000000000' + assert daemon_stats['notarizedtxid'] != '0000000000000000000000000000000000000000000000000000000000000000' + return True + + +def validate_proxy(env_params_dictionary, proxy, node=0): + attempts = 0 + while True: # base connection check + try: + getinfo_output = proxy.getinfo() + print(getinfo_output) + break + except Exception as e: + print("Coennction failed, error: ", e, "\nRetrying") + attempts += 1 + time.sleep(10) + if attempts > 15: + raise ChildProcessError("Node ", node, " does not respond") + print("IMPORTING PRIVKEYS") + res = proxy.importprivkey(env_params_dictionary.get('test_wif')[node], '', True) + print(res) + assert proxy.validateaddress(env_params_dictionary.get('test_address')[node])['ismine'] + try: + pubkey = env_params_dictionary.get('test_pubkey')[node] + assert proxy.getinfo()['pubkey'] == pubkey + except (KeyError, IndexError): + print("\nNo -pubkey= runtime parameter specified") + assert proxy.verifychain() + time.sleep(15) + print("\nBalance: " + str(proxy.getbalance())) + print("Each node should have at least 777 coins to perform CC tests\n") + + +def enable_mining(proxy): + cores = os.cpu_count() + if cores > 2: + threads_count = cores - 2 + else: + threads_count = 1 + tries = 0 + while True: + try: + proxy.setgenerate(True, threads_count) + break + except (RPCError, HttpError) as e: + print(e, " Waiting chain startup\n") + time.sleep(10) + tries += 1 + if tries > 30: + raise ChildProcessError("Node did not start correctly, aborting\n") + + +def mine_and_waitconfirms(txid, proxy, confs_req=2): # should be used after tx is send + # we need the tx above to be confirmed in the next block + attempts = 0 + while True: + try: + confirmations_amount = proxy.getrawtransaction(txid, 1)['confirmations'] + if confirmations_amount < confs_req: + print("\ntx is not confirmed yet! Let's wait a little more") + time.sleep(5) + else: + print("\ntx confirmed") + return True + except KeyError as e: + print("\ntx is in mempool still probably, let's wait a little bit more\nError: ", e) + time.sleep(6) + attempts += 1 + if attempts < 100: + pass + else: + print("\nwaited too long - probably tx stuck by some reason") + return False + + +def validate_transaction(proxy, txid, conf_req): + try: + isinstance(proxy, Proxy) + except Exception as e: + raise TypeError("Not a Proxy object, error: " + str(e)) + conf = 0 + while conf < conf_req: + print("\nWaiting confirmations...") + resp = proxy.gettransaction(txid) + conf = resp.get('confirmations') + time.sleep(2) + + +def validate_template(blocktemplate, schema=''): # BIP 0022 + blockschema = { + 'type': 'object', + 'required': ['bits', 'curtime', 'height', 'previousblockhash', 'version', 'coinbasetxn'], + 'properties': { + 'capabilities': {'type': 'array', + 'items': {'type': 'string'}}, + 'version': {'type': ['integer', 'number']}, + 'previousblockhash': {'type': 'string'}, + 'finalsaplingroothash': {'type': 'string'}, + 'transactions': {'type': 'array', + 'items': {'type': 'object'}}, + 'coinbasetxn': {'type': 'object', + 'required': ['data', 'hash', 'depends', 'fee', 'required', 'sigops'], + 'properties': { + 'data': {'type': 'string'}, + 'hash': {'type': 'string'}, + 'depends': {'type': 'array'}, + 'fee': {'type': ['integer', 'number']}, + 'sigops': {'type': ['integer', 'number']}, + 'coinbasevalue': {'type': ['integer', 'number']}, + 'required': {'type': 'boolean'} + } + }, + 'longpollid': {'type': 'string'}, + 'target': {'type': 'string'}, + 'mintime': {'type': ['integer', 'number']}, + 'mutable': {'type': 'array', + 'items': {'type': 'string'}}, + 'noncerange': {'type': 'string'}, + 'sigoplimit': {'type': ['integer', 'number']}, + 'sizelimit': {'type': ['integer', 'number']}, + 'curtime': {'type': ['integer', 'number']}, + 'bits': {'type': 'string'}, + 'height': {'type': ['integer', 'number']} + } + } + if not schema: + schema = blockschema + jsonschema.validate(instance=blocktemplate, schema=schema) + + +def check_synced(*proxies): + for proxy in proxies: + tries = 0 + while True: + check = proxy.getinfo().get('synced') + proxy.ping() + if check: + print("Synced\n") + break + else: + print("Waiting for sync\nAttempt: ", tries + 1, "\n") + time.sleep(10) + tries += 1 + if tries > 120: # up to 20 minutes + return False + return True + + +def randomstring(length): + chars = string.ascii_letters + return ''.join(random.choice(chars) for i in range(length)) + + +def in_99_range(compare, base): + if compare >= 0.99*base: + return True + else: + return False + + +def compare_rough(base, comp, limit=30): + if base >= comp - limit: + return True + else: + return False + + +def collect_orderids(rpc_response, dict_key): # see dexp2p tests in modules + orderids = [] + for item in rpc_response.get(dict_key): + orderids.append(str(item.get('id'))) + return orderids + + +def randomhex(): # returns 64 chars long pubkey-like hex string + chars = string.hexdigits + return (''.join(random.choice(chars) for i in range(64))).lower() + + +def write_file(filename): # creates text file + lines = 10 + content = '' + for x in range(lines): + content += randomhex() + '\n' + with open(filename, 'w') as f: + f.write(str('filename\n')) + f.write(content) + return True + + +def write_empty_file(filename: str, size: int): # creates empty file slightly bigger than size in mb + if os.path.isfile(filename): + os.remove(filename) + with open(filename, 'wb') as f: + f.seek((size * 1024 * 1025) - 1) + f.write(b'\0') + + +def get_size(file): + if os.path.isfile(file): + return os.path.getsize(file) + else: + raise FileNotFoundError + + +def get_filehash(file): + if os.path.isfile(file): + with open(file, "rb") as f: + bytez = f.read() # read entire file as bytes + fhash = hashlib.sha256(bytez).hexdigest() + return str(fhash) + else: + raise FileNotFoundError + + +def validate_tx_pattern(txid): + if not isinstance(txid, str): + return False + pattern = re.compile('[0-9a-f]{64}') + if pattern.match(txid): + return True + else: + return False + + +def validate_raddr_pattern(addr): + if not isinstance(addr, str): + return False + address_pattern = re.compile(r"R[a-zA-Z0-9]{33}\Z") + if address_pattern.match(addr): + return True + else: + return False + + +def wait_blocks(rpc_connection, blocks_to_wait): + init_height = int(rpc_connection.getinfo()["blocks"]) + while True: + current_height = int(rpc_connection.getinfo()["blocks"]) + height_difference = current_height - init_height + if height_difference < blocks_to_wait: + print("Waiting for more blocks") + time.sleep(5) + else: + return True \ No newline at end of file diff --git a/qa/pytest_komodo/cc_modules/util.py b/qa/pytest_komodo/lib/util.py similarity index 95% rename from qa/pytest_komodo/cc_modules/util.py rename to qa/pytest_komodo/lib/util.py index eb37fc641dc..60f8a018ff4 100644 --- a/qa/pytest_komodo/cc_modules/util.py +++ b/qa/pytest_komodo/lib/util.py @@ -3,10 +3,7 @@ import sys from random import choice from string import ascii_uppercase -try: - from slickrpc import Proxy -except ImportError: - from bitcoinrpc.authproxy import AuthServiceProxy as Proxy +from slickrpc import Proxy def assert_success(result): diff --git a/qa/pytest_komodo/modules/test_dexp2p.py b/qa/pytest_komodo/modules/test_dexp2p.py index 3645f9167ee..e42d8a0fa00 100644 --- a/qa/pytest_komodo/modules/test_dexp2p.py +++ b/qa/pytest_komodo/modules/test_dexp2p.py @@ -10,7 +10,7 @@ import time sys.path.append('../') -from basic.pytest_util import validate_template, randomhex, write_file, write_empty_file +from lib.pytest_util import validate_template, randomhex, write_file, write_empty_file @pytest.mark.usefixtures("proxy_connection") diff --git a/qa/pytest_komodo/modules/test_dexp2p_e2e.py b/qa/pytest_komodo/modules/test_dexp2p_e2e.py index 062a86edb9e..a633f34e333 100644 --- a/qa/pytest_komodo/modules/test_dexp2p_e2e.py +++ b/qa/pytest_komodo/modules/test_dexp2p_e2e.py @@ -10,7 +10,7 @@ import os sys.path.append('../') -from basic.pytest_util import randomstring, in_99_range, collect_orderids, check_synced, \ +from lib.pytest_util import randomstring, in_99_range, collect_orderids, check_synced, \ get_size, write_file, get_filehash, compare_rough, write_empty_file diff --git a/qa/pytest_komodo/nodesconfig.json b/qa/pytest_komodo/nodesconfig.json index df8792e4c26..5b5aedac64e 100644 --- a/qa/pytest_komodo/nodesconfig.json +++ b/qa/pytest_komodo/nodesconfig.json @@ -5,9 +5,9 @@ "rpc_ip" : "127.0.0.1", "rpc_port": 7000, "net_port": 6000, - "pubkey" : "02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7", - "address": "RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd", - "txid": "e9945094eb1a9028afd310719aea21966425ceccc3f8c0972277a96201ca1b81" + "pubkey" : "02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9", + "address": "RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein", + "txid": "3376a48a7daf543d8401e072102d4e93f53f300a101bd67e82820d2da0f2729e" }, "node2" : { "rpc_user" : "test", @@ -25,9 +25,9 @@ "rpc_ip" : "127.0.0.1", "rpc_port": 7002, "net_port": 6002, - "pubkey" : "02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9", - "address": "RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein", - "txid": "3376a48a7daf543d8401e072102d4e93f53f300a101bd67e82820d2da0f2729e" + "pubkey" : "02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7", + "address": "RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd", + "txid": "e9945094eb1a9028afd310719aea21966425ceccc3f8c0972277a96201ca1b81" }, "is_fresh_chain": true } \ No newline at end of file diff --git a/qa/pytest_komodo/start_ci.bat b/qa/pytest_komodo/start_ci.bat index ad430fd23d5..31fdb27ae30 100644 --- a/qa/pytest_komodo/start_ci.bat +++ b/qa/pytest_komodo/start_ci.bat @@ -1,14 +1,14 @@ set CLIENTS=2 set CHAIN=TONYCI -set TEST_ADDY0=RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd -set TEST_WIF0=UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN -set TEST_PUBKEY0=02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7 +set TEST_ADDY0=RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein +set TEST_WIF0=UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr +set TEST_PUBKEY0=02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9 set TEST_ADDY1=RHoTHYiHD8TU4k9rbY4Aoj3ztxUARMJikH set TEST_WIF1=UwmmwgfXwZ673brawUarPzbtiqjsCPWnG311ZRAL4iUCZLBLYeDu set TEST_PUBKEY1=0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149 set CHAIN_MODE=REGULAR set IS_BOOTSTRAP_NEEDED=True -set BOOTSTRAP_URL=https://sirseven.me/share/bootstrap.tar.gz +set BOOTSTRAP_URL=https://sirseven.me/share/bootstrap4.tar.gz python.exe chainstart.py diff --git a/qa/pytest_komodo/start_set_dex.bat b/qa/pytest_komodo/start_set_dex.bat index acf88c2e6b2..2131d876ed1 100644 --- a/qa/pytest_komodo/start_set_dex.bat +++ b/qa/pytest_komodo/start_set_dex.bat @@ -1,17 +1,17 @@ set CLIENTS=2 set CHAIN=TONYCI -set TEST_ADDY0=RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd -set TEST_WIF0=UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN -set TEST_PUBKEY0=02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7 +set TEST_ADDY0=RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein +set TEST_WIF0=UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr +set TEST_PUBKEY0=02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9 set TEST_ADDY1=RHoTHYiHD8TU4k9rbY4Aoj3ztxUARMJikH set TEST_WIF1=UwmmwgfXwZ673brawUarPzbtiqjsCPWnG311ZRAL4iUCZLBLYeDu set TEST_PUBKEY1=0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149 -set TEST_ADDY2=RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein -set TEST_WIF2=UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr -set TEST_PUBKEY2=02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9 +set TEST_ADDY2=RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd +set TEST_WIF2=UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN +set TEST_PUBKEY2=02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7 set CHAIN_MODE=DEX2 set IS_BOOTSTRAP_NEEDED=True -set BOOTSTRAP_URL=https://sirseven.me/share/bootstrap.tar.gz +set BOOTSTRAP_URL=https://sirseven.me/share/bootstrap4.tar.gz python.exe chainstart.py diff --git a/qa/pytest_komodo/sync/pytest_util.py b/qa/pytest_komodo/sync/pytest_util.py deleted file mode 100644 index 1850475bde2..00000000000 --- a/qa/pytest_komodo/sync/pytest_util.py +++ /dev/null @@ -1,52 +0,0 @@ -import os -import requests -import json - - -def env_get(var, default): - try: - res = os.environ[var] - except KeyError: - res = default - return res - - -def get_chainstate(proxy): - vals = {} - res = proxy.getinfo() - vals.update({'synced': res.get('synced')}) - vals.update({'notarized': res.get('notarized')}) - vals.update({'blocks': res.get('blocks')}) - vals.update({'longestchain': res.get('longestchain')}) - return vals - - -def get_notary_stats(): - api = "https://komodostats.com/api/notary/summary.json" - local = "notary.json" - data = requests.get(api).json() - with open(local, 'w') as lf: - lf.write(str(data)) - return data - - -def check_notarized(proxy, api_stats, coin, blocktime=60): - maxblocksdiff = round(1500 / blocktime) - daemon_stats = proxy.getinfo() - notarizations = {} - for item in api_stats: - if item.get('ac_name') == coin: - notarizations = item - if not notarizations: - raise BaseException("Chain notary data not found") - if daemon_stats['notarized'] == notarizations['notarized']: - assert daemon_stats['notarizedhash'] == notarizations['notarizedhash'] - assert daemon_stats['notarizedtxid'] == notarizations['notarizedtxid'] - return True - elif abs(daemon_stats['notarazied'] - notarizations['notarized']) >= maxblocksdiff: - return False - else: - assert daemon_stats['notarized'] - assert daemon_stats['notarizedhash'] != '0000000000000000000000000000000000000000000000000000000000000000' - assert daemon_stats['notarizedtxid'] != '0000000000000000000000000000000000000000000000000000000000000000' - return True diff --git a/qa/pytest_komodo/sync/test_sync.py b/qa/pytest_komodo/sync/test_sync.py index ecb53f4478b..7506ec6710e 100644 --- a/qa/pytest_komodo/sync/test_sync.py +++ b/qa/pytest_komodo/sync/test_sync.py @@ -5,7 +5,7 @@ import pytest import time -from pytest_util import env_get, get_chainstate, check_notarized, get_notary_stats +from lib.pytest_util import env_get, get_chainstate, check_notarized, get_notary_stats @pytest.mark.usefixtures("proxy_connection") From d0f1c8a8b5bc6ad23843662e84629ed5383bcae2 Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Thu, 23 Feb 2023 22:51:26 +0300 Subject: [PATCH 02/13] remove unused tests, switch to requests lib for pytests, fix tests compatibility with dev --- qa/pytest_komodo/basic/test_blocks.py | 52 +-- qa/pytest_komodo/cc_modules/test_channels.py | 18 +- qa/pytest_komodo/cc_modules/test_dice.py | 2 +- qa/pytest_komodo/cc_modules/test_faucet.py | 5 +- qa/pytest_komodo/cc_modules/test_oracles.py | 3 +- qa/pytest_komodo/cc_modules/test_rewards.py | 3 +- qa/pytest_komodo/cc_modules/test_token.py | 18 +- qa/pytest_komodo/cc_modules/test_tokenv2.py | 314 ------------------ .../cc_modules/test_unspentccundex.py | 142 -------- qa/pytest_komodo/chainconfig.json | 34 +- qa/pytest_komodo/ci_set_dex.sh | 14 +- qa/pytest_komodo/ci_setup.sh | 8 +- qa/pytest_komodo/conftest.py | 8 +- qa/pytest_komodo/lib/komodo_requests.py | 39 +++ qa/pytest_komodo/lib/pytest_util.py | 12 +- qa/pytest_komodo/lib/util.py | 2 +- qa/pytest_komodo/nodesconfig.json | 12 +- qa/pytest_komodo/start_ci.bat | 8 +- qa/pytest_komodo/start_set_dex.bat | 14 +- 19 files changed, 107 insertions(+), 601 deletions(-) delete mode 100644 qa/pytest_komodo/cc_modules/test_tokenv2.py delete mode 100644 qa/pytest_komodo/cc_modules/test_unspentccundex.py create mode 100644 qa/pytest_komodo/lib/komodo_requests.py diff --git a/qa/pytest_komodo/basic/test_blocks.py b/qa/pytest_komodo/basic/test_blocks.py index 7bbe094c045..907bf5a7deb 100644 --- a/qa/pytest_komodo/basic/test_blocks.py +++ b/qa/pytest_komodo/basic/test_blocks.py @@ -4,7 +4,7 @@ # file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest -from lib.pytest_util import validate_transaction, validate_template +from lib.pytest_util import validate_template from decimal import * @@ -308,56 +308,6 @@ def test_gettxoutsetinfo(self, test_params): res = rpc.gettxoutsetinfo() validate_template(res, schema) - def test_kvupdate(self, test_params): - test_values = { - 'v_key': 'valid_key', - 'value': 'test+value', - 'days': '2', - 'pass': 'secret', - 'n_key': 'invalid_key', - 'keylen': 9 - } - rpc = test_params.get('node1').get('rpc') - res = rpc.kvupdate(test_values['v_key'], test_values['value'], test_values['days'], test_values['pass']) - assert res.get('key') == test_values['v_key'] - assert res.get('keylen') == test_values['keylen'] - assert res.get('value') == test_values['value'] - - def test_getrawmempool(self, test_params): - test_values = { - 'key': 'mempool_key', - 'value': 'key_value', - 'days': '1', - 'pass': 'secret' - } # to get info into mempool, we need to create tx, kvupdate call creates one for us - rpc = test_params.get('node1').get('rpc') - res = rpc.kvupdate(test_values['key'], test_values['value'], test_values['days'], test_values['pass']) - txid = res.get('txid') - kvheight = res.get('height') - res = rpc.getrawmempool() - assert txid in res - res = rpc.getrawmempool(False) # False is default value, res should be same as in call above - assert txid in res - res = rpc.getrawmempool(True) - assert res.get(txid).get('height') == kvheight - - def test_kvsearch(self, test_params): - test_values = { - 'key': 'search_key', - 'value': 'search_value', - 'days': '1', - 'pass': 'secret' - } - rpc = test_params.get('node1').get('rpc') - res = rpc.kvupdate(test_values['key'], test_values['value'], test_values['days'], test_values['pass']) - txid = res.get('txid') - keylen = res.get('keylen') - validate_transaction(rpc, txid, 1) # wait for block - res = rpc.kvsearch(test_values['key']) - assert res.get('key') == test_values['key'] - assert res.get('keylen') == keylen - assert res.get('value') == test_values['value'] - def test_notaries(self, test_params): rpc = test_params.get('node1').get('rpc') res = rpc.notaries('1') diff --git a/qa/pytest_komodo/cc_modules/test_channels.py b/qa/pytest_komodo/cc_modules/test_channels.py index b071090952c..5c55766bae7 100644 --- a/qa/pytest_komodo/cc_modules/test_channels.py +++ b/qa/pytest_komodo/cc_modules/test_channels.py @@ -5,7 +5,7 @@ import pytest import time -from lib.pytest_util import validate_template, mine_and_waitconfirms, validate_raddr_pattern, validate_tx_pattern +from lib.pytest_util import validate_template, mine_and_waitconfirms, validate_raddr_pattern @pytest.mark.usefixtures("proxy_connection", "test_params") @@ -154,14 +154,14 @@ def test_channels_closenrefund(self, channel_instance): txid = rpc1.sendrawtransaction(res.get('hex')) mine_and_waitconfirms(txid, rpc1) res = rpc1.channelsclose(newchannel.get('open_txid')) - validate_template(res, channels_refund_close_schema) - close_txid = rpc1.sendrawtransaction(res.get('hex')) + assert isinstance(res, str) + close_txid = rpc1.sendrawtransaction(res) mine_and_waitconfirms(close_txid, rpc1) # execute refund res = rpc1.channelsrefund(newchannel.get('open_txid'), close_txid) - validate_template(res, channels_refund_close_schema) - refund_txid = rpc1.sendrawtransaction(res.get('hex')) + assert isinstance(res, str) + refund_txid = rpc1.sendrawtransaction(res) mine_and_waitconfirms(refund_txid, rpc1) @@ -217,8 +217,8 @@ def test_channels_flow(self, channel_instance): # executing channel close res = rpc1.channelsclose(channel.get('open_txid')) - assert res.get('result') == 'success' - close_txid = rpc1.sendrawtransaction(res.get('hex')) + assert isinstance(res, str) + close_txid = rpc1.sendrawtransaction(res) mine_and_waitconfirms(close_txid, rpc1) # now in channelinfo closed flag should appear @@ -227,8 +227,8 @@ def test_channels_flow(self, channel_instance): # executing channel refund res = rpc1.channelsrefund(channel.get('open_txid'), close_txid) - assert res.get('result') == 'success' - refund_txid = rpc1.sendrawtransaction(res.get('hex')) + assert isinstance(res, str) + refund_txid = rpc1.sendrawtransaction(res) mine_and_waitconfirms(refund_txid, rpc1) # checking if it refunded to opener address diff --git a/qa/pytest_komodo/cc_modules/test_dice.py b/qa/pytest_komodo/cc_modules/test_dice.py index 14a7bf51590..9143388fcb8 100644 --- a/qa/pytest_komodo/cc_modules/test_dice.py +++ b/qa/pytest_komodo/cc_modules/test_dice.py @@ -4,7 +4,7 @@ # file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest -from lib.pytest_util import validate_template, mine_and_waitconfirms, randomstring,\ +from lib.pytest_util import validate_template, randomstring,\ randomhex, wait_blocks, validate_raddr_pattern, check_synced from decimal import * diff --git a/qa/pytest_komodo/cc_modules/test_faucet.py b/qa/pytest_komodo/cc_modules/test_faucet.py index 49fb1cc91b3..347dbaa2d07 100644 --- a/qa/pytest_komodo/cc_modules/test_faucet.py +++ b/qa/pytest_komodo/cc_modules/test_faucet.py @@ -5,7 +5,6 @@ import pytest import re -from slickrpc import exc import warnings from lib.pytest_util import validate_template, mine_and_waitconfirms @@ -87,7 +86,7 @@ def test_faucetget(self, test_params): vout_fauc = res.get('vout')[1] assert node_addr in vout_fauc.get('scriptPubKey').get('addresses') assert vout_fauc.get('valueZat') == pow(10, 8) * vout_fauc.get('value') - except (KeyError, TypeError, exc.RpcTypeError): + except (KeyError, TypeError): assert res.get('result') == 'error' @@ -128,5 +127,5 @@ def test_faucetget_mine(self, test_params): fhex = res.get('hex') txid = rpc1.sendrawtransaction(fhex) mine_and_waitconfirms(txid, rpc1) - except exc.RpcVerifyRejected: # excepts scenario when pubkey already received faucet funds + except Exception: # excepts scenario when pubkey already received faucet funds warnings.warn(RuntimeWarning('Faucet funds were already claimed by pubkey')) diff --git a/qa/pytest_komodo/cc_modules/test_oracles.py b/qa/pytest_komodo/cc_modules/test_oracles.py index 1b3fa5e4a8b..bcbdcc83917 100644 --- a/qa/pytest_komodo/cc_modules/test_oracles.py +++ b/qa/pytest_komodo/cc_modules/test_oracles.py @@ -4,9 +4,8 @@ # file COPYING or https://www.opensource.org/licenses/mit-license.php. import pytest -from slickrpc.exc import RpcException as RPCError from lib.pytest_util import validate_template, mine_and_waitconfirms, randomstring,\ - randomhex, validate_raddr_pattern + validate_raddr_pattern @pytest.mark.usefixtures("proxy_connection", "test_params") diff --git a/qa/pytest_komodo/cc_modules/test_rewards.py b/qa/pytest_komodo/cc_modules/test_rewards.py index 6f3a733d688..ed7130c7af8 100644 --- a/qa/pytest_komodo/cc_modules/test_rewards.py +++ b/qa/pytest_komodo/cc_modules/test_rewards.py @@ -5,8 +5,7 @@ import pytest import time -from lib.pytest_util import validate_template, mine_and_waitconfirms, validate_raddr_pattern, \ - randomstring, randomhex +from lib.pytest_util import validate_template, validate_raddr_pattern, randomhex @pytest.mark.usefixtures("proxy_connection", "test_params") diff --git a/qa/pytest_komodo/cc_modules/test_token.py b/qa/pytest_komodo/cc_modules/test_token.py index 64e0a0bceca..87bdc8febe2 100644 --- a/qa/pytest_komodo/cc_modules/test_token.py +++ b/qa/pytest_komodo/cc_modules/test_token.py @@ -4,7 +4,6 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. import pytest -from slickrpc.exc import RpcException as RPCError from lib.pytest_util import validate_template, mine_and_waitconfirms, randomstring, randomhex, validate_raddr_pattern @@ -164,7 +163,6 @@ def test_tokenask_bid_orders(self, token_instance): rpc1 = token_instance.rpc[0] rpc2 = token_instance.rpc[1] - pubkey2 = token_instance.pubkey[1] if not token_instance.base_token: token_instance.new_token(token_instance.rpc[1]) @@ -243,9 +241,9 @@ def test_bad_calls(self, token_instance): tokenid = token_instance.base_token.get('tokenid') # trying to create token with negative supply - with pytest.raises(RPCError): - res = rpc.tokencreate("NUKE", "-1987420", "no bueno supply") - assert res.get('error') + # with pytest.raises(ConnectionError): + res = rpc.tokencreate("NUKE", "-1987420", "no bueno supply") + assert res.get('error') # creating token with name more than 32 chars res = rpc.tokencreate("NUKE123456789012345678901234567890", "1987420", "name too long") assert res.get('error') @@ -269,9 +267,8 @@ def test_bad_calls(self, token_instance): res = rpc.tokenbid("0", tokenid, "1") assert res.get('error') # invalid price bid - with pytest.raises(RPCError): - res = rpc.tokenbid("1", tokenid, "-1") - assert res.get('error') + res = rpc.tokenbid("1", tokenid, "-1") + assert res.get('error') # invalid price bid res = rpc.tokenbid("1", tokenid, "0") assert res.get('error') @@ -285,9 +282,8 @@ def test_bad_calls(self, token_instance): res = rpc.tokenask("0", tokenid, "1") assert res.get('error') # invalid price ask - with pytest.raises(RPCError): - res = rpc.tokenask("1", tokenid, "-1") - assert res.get('error') + res = rpc.tokenask("1", tokenid, "-1") + assert res.get('error') # invalid price ask res = rpc.tokenask("1", tokenid, "0") assert res.get('error') diff --git a/qa/pytest_komodo/cc_modules/test_tokenv2.py b/qa/pytest_komodo/cc_modules/test_tokenv2.py deleted file mode 100644 index b42d9ab2bcc..00000000000 --- a/qa/pytest_komodo/cc_modules/test_tokenv2.py +++ /dev/null @@ -1,314 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2021 SuperNET developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or https://www.opensource.org/licenses/mit-license.php. - -import pytest -from slickrpc.exc import RpcException as RPCError -from lib.pytest_util import validate_template, mine_and_waitconfirms, randomstring, randomhex, validate_raddr_pattern - - -@pytest.mark.usefixtures("proxy_connection") -class TestTokenCCv2Calls: - - @staticmethod - def new_token(proxy, schema=None): - name = randomstring(8) - amount = '0.10000000' - res = proxy.tokenv2create(name, amount, "test token 1") - if schema: - validate_template(res, schema) - assert res.get('result') == 'success' - txid = proxy.sendrawtransaction(res.get('hex')) - mine_and_waitconfirms(txid, proxy) - token = { - 'tokenid': txid, - 'name': name - } - return token - - def test_tokenv2create_v2list_v2info(self, test_params): - v2create_schema = { - 'type': 'object', - 'properties': { - 'result': {'type': 'string'}, - 'hex': {'type': 'string'}, - 'error': {'type': 'string'} - }, - 'required': ['result'] - } - - v2list_schema = { - 'type': 'array', - 'items': {'type': 'string'} - } - - v2info_schema = { - 'type': 'object', - 'properties': { - 'result': {'type': 'string'}, - 'tokenid': {'type': 'string'}, - 'owner': {'type': 'string'}, - 'name': {'type': 'string'}, - 'supply': {'type': 'integer'}, - 'description': {'type': 'string'}, - 'version': {'type': 'integer'}, - 'IsMixed': {'type': 'string'} - }, - 'required': ['result'] - } - - rpc = test_params.get('node1').get('rpc') - token = self.new_token(rpc, schema=v2create_schema) - - res = rpc.tokenv2list() - validate_template(res, v2list_schema) - - res = rpc.tokenv2info(token.get('tokenid')) - validate_template(res, v2info_schema) - - def test_tokenv2address(self, test_params): - v2assetaddress_schema = { - 'type': 'object', - 'properties': { - 'result': {'type': 'string'}, - "GlobalPk Assetsv2 CC Address": {'type': 'string'}, - "GlobalPk Assetsv2 CC Balance": {'type': 'number'}, - "GlobalPk Assetsv2 Normal Address": {'type': 'string'}, - "GlobalPk Assetsv2 Normal Balance": {'type': 'number'}, - "GlobalPk Assetsv2/Tokens CC Address": {'type': 'string'}, - "pubkey Assetsv2 CC Address": {'type': 'string'}, - "pubkey Assetsv2 CC Balance": {'type': 'number'}, - "mypk Assetsv2 CC Address": {'type': 'string'}, - "mypk Assetsv2 CC Balance": {'type': 'number'}, - "mypk Normal Address": {'type': 'string'}, - "mypk Normal Balance": {'type': 'number'} - }, - 'required': ['result'] - } - - v2tokenaddress_schema = { - 'type': 'object', - 'properties': { - 'result': {'type': 'string'}, - "GlobalPk Tokensv2 CC Address": {'type': 'string'}, - "GlobalPk Tokensv2 CC Balance": {'type': 'number'}, - "GlobalPk Tokensv2 Normal Address": {'type': 'string'}, - "GlobalPk Tokensv2 Normal Balance": {'type': 'number'}, - "pubkey Tokensv2 CC Address": {'type': 'string'}, - "pubkey Tokensv2 CC Balance": {'type': 'number'}, - "mypk Tokensv2 CC Address": {'type': 'string'}, - "mypk Tokensv2 CC Balance": {'type': 'number'}, - "mypk Normal Address": {'type': 'string'}, - "mypk Normal Balance": {'type': 'number'} - }, - 'required': ['result'] - } - - rpc = test_params.get('node1').get('rpc') - pubkey = test_params.get('node1').get('pubkey') - - res = rpc.assetsv2address(pubkey) - validate_template(res, v2assetaddress_schema) - - res = rpc.tokenv2address(pubkey) - validate_template(res, v2tokenaddress_schema) - - def test_tokenv2transfer_v2balance(self, test_params): - v2transfer_schema = { - 'type': 'object', - 'properties': { - 'result': {'type': 'string'}, - 'hex': {'type': 'string'} - }, - 'required': ['result'] - } - - v2balance_schema = { - 'type': 'object', - 'properties': { - 'result': {'type': 'string'}, - 'CCaddress': {'type': 'string'}, - 'tokenid': {'type': 'string'}, - 'balance': {'type': 'integer'} - }, - 'required': ['result'] - } - - rpc1 = test_params.get('node1').get('rpc') - rpc2 = test_params.get('node2').get('rpc') - pubkey2 = test_params.get('node2').get('pubkey') - - token1 = self.new_token(rpc1) - - amount = 150 - res = rpc1.tokenv2transfer(token1.get('tokenid'), pubkey2, str(amount)) - validate_template(res, v2transfer_schema) - txid = rpc1.sendrawtransaction(res.get('hex')) - mine_and_waitconfirms(txid, rpc1) - - res = rpc2.tokenv2balance(token1.get('tokenid'), pubkey2) - validate_template(res, v2balance_schema) - assert amount == res.get('balance') - assert token1.get('tokenid') == res.get('tokenid') - - def test_tokenv2ask_v2bid_v2orders(self, test_params): - v2askbid_schema = { - 'type': 'object', - 'properties': { - 'hex': {'type': 'string'} - }, - 'required': ['hex'] - } - - v2orders_schema = { - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'funcid': {'type': 'string'}, - 'txid': {'type': 'string'}, - 'vout': {'type': 'integer'}, - 'amount': {'type': 'string'}, - 'askamount': {'type': 'string'}, - 'origaddress': {'type': 'string'}, - 'origtokenaddress': {'type': 'string'}, - 'tokenid': {'type': 'string'}, - 'totalrequired': {'type': ['string', 'integer']}, - 'price': {'type': ['integer', 'number']} - } - } - } - - rpc1 = test_params.get('node1').get('rpc') - rpc2 = test_params.get('node2').get('rpc') - pubkey2 = test_params.get('node2').get('pubkey') - - token1 = self.new_token(rpc1) - amount1 = 150 - amount2 = 100 - price = 0.1 - - res = rpc1.tokenv2ask(str(amount1), token1.get('tokenid'), price) - validate_template(res, v2askbid_schema) - asktxid = rpc1.sendrawtransaction(res.get('hex')) - mine_and_waitconfirms(asktxid, rpc1) - - res = rpc1.tokenv2bid(str(amount2), token1.get('tokenid'), price) - validate_template(res, v2askbid_schema) - bidtxid = rpc1.sendrawtransaction(res.get('hex')) - mine_and_waitconfirms(bidtxid, rpc1) - - # Check orders and myorders call - orders1 = rpc2.tokenv2orders(token1.get('tokenid')) - validate_template(orders1, v2orders_schema) - orders2 = rpc1.mytokenv2orders(token1.get('tokenid')) - validate_template(orders2, v2orders_schema) - assert orders1 == orders2 - - # Check fills and cancel calls - res = rpc2.tokenv2fillask(token1.get('tokenid'), asktxid, str(int(amount1 * 0.5))) - validate_template(res, v2askbid_schema) - asktxid2 = rpc2.sendrawtransaction(res.get('hex')) - mine_and_waitconfirms(asktxid2, rpc2) - - res = rpc2.tokenv2fillbid(token1.get('tokenid'), bidtxid, str(int(amount2 * 0.5))) - validate_template(res, v2askbid_schema) - bidtxid2 = rpc2.sendrawtransaction(res.get('hex')) - mine_and_waitconfirms(bidtxid2, rpc2) - - res = rpc1.tokenv2cancelask(token1.get('tokenid'), asktxid2) - validate_template(res, v2askbid_schema) - txid = rpc1.sendrawtransaction(res.get('hex')) - mine_and_waitconfirms(txid, rpc1) - - res = rpc1.tokenv2cancelbid(token1.get('tokenid'), bidtxid2) - validate_template(res, v2askbid_schema) - txid = rpc1.sendrawtransaction(res.get('hex')) - mine_and_waitconfirms(txid, rpc1) - - # There should be no orders left after cancelling - orders = rpc1.mytokenv2orders(token1.get('tokenid')) - validate_template(orders, v2orders_schema) - assert len(orders) == 0 - - -@pytest.mark.usefixtures("proxy_connection") -class TestTokenCCv2: - - def test_rewardsaddress(self, test_params): - rpc = test_params.get('node1').get('rpc') - pubkey = test_params.get('node1').get('pubkey') - - res = rpc.assetsv2address(pubkey) - for key in res.keys(): - if key.find('ddress') > 0: - assert validate_raddr_pattern(res.get(key)) - - res = rpc.tokenv2address(pubkey) - for key in res.keys(): - if key.find('ddress') > 0: - assert validate_raddr_pattern(res.get(key)) - - @staticmethod - def bad_calls(proxy, token, pubkey): - name = token.get('name') - tokenid = token.get('tokenid') - # trying to create token with negative supply - with pytest.raises(RPCError): - res = proxy.tokenv2create("NUKE", "-1987420", "no bueno supply") - assert res.get('error') - # creating token with name more than 32 chars - res = proxy.tokenv2create("NUKE123456789012345678901234567890", "1987420", "name too long") - assert res.get('error') - # getting token balance for non existing tokenid - res = proxy.tokenv2balance("", pubkey) - assert res.get('error') - # no info for invalid tokenid - res = proxy.tokenv2info(pubkey) - assert res.get('error') - # invalid token transfer amount - randompubkey = randomhex() - res = proxy.tokenv2transfer(tokenid, randompubkey, "0") - assert res.get('error') - # invalid token transfer amount - res = proxy.tokenv2transfer(tokenid, randompubkey, "-1") - assert res.get('error') - # invalid numtokens bid - res = proxy.tokenv2bid("-1", tokenid, "1") - assert res.get('error') - # invalid numtokens bid - res = proxy.tokenv2bid("0", tokenid, "1") - assert res.get('error') - # invalid price bid - with pytest.raises(RPCError): - res = proxy.tokenv2bid("1", tokenid, "-1") - assert res.get('error') - # invalid price bid - res = proxy.tokenv2bid("1", tokenid, "0") - assert res.get('error') - # invalid tokenid bid - res = proxy.tokenv2bid("100", "deadbeef", "1") - assert res.get('error') - # invalid numtokens ask - res = proxy.tokenv2ask("-1", tokenid, "1") - assert res.get('error') - # invalid numtokens ask - res = proxy.tokenv2ask("0", tokenid, "1") - assert res.get('error') - # invalid price ask - with pytest.raises(RPCError): - res = proxy.tokenv2ask("1", tokenid, "-1") - assert res.get('error') - # invalid price ask - res = proxy.tokenv2ask("1", tokenid, "0") - assert res.get('error') - # invalid tokenid ask - res = proxy.tokenv2ask("100", "deadbeef", "1") - assert res.get('error') - - def test_bad_calls(self, test_params): - rpc = test_params.get('node1').get('rpc') - pubkey = test_params.get('node1').get('pubkey') - token = TestTokenCCv2Calls.new_token(rpc) - self.bad_calls(rpc, token, pubkey) diff --git a/qa/pytest_komodo/cc_modules/test_unspentccundex.py b/qa/pytest_komodo/cc_modules/test_unspentccundex.py deleted file mode 100644 index 139fbe19c64..00000000000 --- a/qa/pytest_komodo/cc_modules/test_unspentccundex.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2020 SuperNET developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or https://www.opensource.org/licenses/mit-license.php. - -# this is a test to check a new index for unspent cc utxos activated with -unspentccindex - -import pytest -import time -from slickrpc.exc import RpcException as RPCError -from lib.util import assert_success, assert_error, mine_and_waitconfirms,\ - send_and_mine, rpc_connect, wait_some_blocks, komodo_teardown - - -@pytest.mark.usefixtures("proxy_connection") -def test_ccindex(test_params): - - # test params inits - rpc = test_params.get('node1').get('rpc') - rpc1 = test_params.get('node2').get('rpc') - - pubkey = test_params.get('node1').get('pubkey') - pubkey1 = test_params.get('node2').get('pubkey') - - is_fresh_chain = test_params.get("is_fresh_chain") - - result = rpc.tokenaddress() - assert_success(result) - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - - # get token cc address for pubkey: - result = rpc.tokenaddress(pubkey) - assert_success(result) - pubkeyTokenCCAddress = "" - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - if x == 'pubkey Tokens CC Address': - pubkeyTokenCCAddress = result[x] - - # get token cc address for pubkey1: - result = rpc.tokenaddress(pubkey1) - assert_success(result) - pubkey1TokenCCAddress = "" - for x in result.keys(): - if x.find('ddress') > 0: - assert result[x][0] == 'R' - if x == 'pubkey Tokens CC Address': - pubkey1TokenCCAddress = result[x] - - # there are no tokens created yet - # TODO: this test conflicts with heir test because token creating for heir -# if is_fresh_chain: -# result = rpc.tokenlist() -# assert result == [] - - print("stop mining to test txns in mempool") - rpc.setgenerate(False) - rpc1.setgenerate(False) - - print("creating test token...") - result = rpc.tokencreate("T1", "20", "token for testing cc index") - assert_success(result) - - tokenid = rpc.sendrawtransaction(result['hex']) - - # check mempool index: - print("check cc index for tokencreate in mempool...") - - # check one utxo in the index - result = rpc.listccunspents(pubkeyTokenCCAddress, tokenid) - # print('type(result)=' + str(type(result))) - assert(str(type(result)) == "") - assert(len(result) == 1) - assert(result[0]['creationId'] == tokenid) - assert(result[0]['txhash'] == tokenid) - assert(result[0]['satoshis'] == 20*100000000) - assert(result[0]['funcid'].upper() == "C") - assert(result[0]['blockHeight'] == 0) # in mempool - - print("check cc index for tokentransfer in mempool...") - - result = rpc.tokentransfer(tokenid, pubkey1, "1") - assert_success(result) - txid = rpc.sendrawtransaction(result['hex']) - - # check two utxos in the mempool index - - result = rpc.listccunspents(pubkeyTokenCCAddress, tokenid) - assert(str(type(result)) == "") - - # note: once I got assert failed here: - # 'E assert 0 == 1' - # probably it happened because setgenerate(False) had not finished atm - assert(len(result) == 1) - assert(result[0]['creationId'] == tokenid) - assert(result[0]['txhash'] == txid) - assert(result[0]['satoshis'] == 20*100000000-1) - assert(result[0]['funcid'].upper() == "T") - assert(result[0]['blockHeight'] == 0) # in mempool - - result = rpc.listccunspents(pubkey1TokenCCAddress, tokenid) - assert(str(type(result)) == "") - assert(len(result) == 1) - assert(result[0]['creationId'] == tokenid) - assert(result[0]['txhash'] == txid) - assert(result[0]['satoshis'] == 1) - assert(result[0]['funcid'].upper() == "T") - assert(result[0]['blockHeight'] == 0) # in mempool - - print("mine txns and check cc index in db...") - - rpc.setgenerate(True, 1) - while True: - print("waiting until mempool empty...") - time.sleep(10) - mempool = rpc.getrawmempool() - if len(mempool) == 0: - break - - result = rpc.listccunspents(pubkeyTokenCCAddress, tokenid) - assert(str(type(result)) == "") - assert(len(result) == 1) - assert(result[0]['creationId'] == tokenid) - assert(result[0]['txhash'] == txid) - assert(result[0]['satoshis'] == 20*100000000-1) - assert(result[0]['funcid'].upper() == "T") - assert(result[0]['blockHeight'] != 0) # not in mempool - - result = rpc.listccunspents(pubkey1TokenCCAddress, tokenid) - assert(str(type(result)) == "") - assert(len(result) == 1) - assert(result[0]['creationId'] == tokenid) - assert(result[0]['txhash'] == txid) - assert(result[0]['satoshis'] == 1) - assert(result[0]['funcid'].upper() == "T") - assert(result[0]['blockHeight'] != 0) # not in mempool - - print("test cc index okay") - diff --git a/qa/pytest_komodo/chainconfig.json b/qa/pytest_komodo/chainconfig.json index faff3c9ee50..57210276beb 100644 --- a/qa/pytest_komodo/chainconfig.json +++ b/qa/pytest_komodo/chainconfig.json @@ -2,38 +2,28 @@ "TONYCI": { "rpc_user": "test", "rpcpassword": "test", - "rpcallowip": "0.0.0.0/0", + "rpcallowip": "127.0.0.1", "rpcport": 7000, "port": 6000, - "rpcbind": "0.0.0.0", + "rpcbind": "127.0.0.1", "ac_name": "TONYCI", "ac_reward": "100000000000", "ac_supply": "10000000000", - "ac_cc": "2", - "ac_blocktime": "30" + "ac_cc": "2" }, - "HUSH3": { + "KMDCI": { "rpc_user": "test", "rpcpassword": "test", - "rpcallowip": "0.0.0.0/0", + "rpcallowip": "127.0.0.1", "rpcport": 7000, - "rpcbind": "0.0.0.0", - "ac_name": "HUSH3", - "ac_sapling": "1", - "ac_reward": "0,1125000000,562500000", - "ac_halving": "129,340000,840000", - "ac_end": "128,340000,5422111", - "ac_eras": "3", - "ac_blocktime": "150", + "port": 6000, + "rpcbind": "127.0.0.1", + "ac_name": "KMDCI", + "ac_reward": "100000000000", + "ac_supply": "10000000000", "ac_cc": "2", - "ac_ccenable": "228,234,235,236,241", - "ac_founders": "1", - "ac_supply": "6178674", - "ac_perc": "11111111", - "clientname": "GoldenSandtrout", - "addnode": "188.165.212.101", - "ac_cclib": "hush3", - "ac_script": "76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac" + "ac_blocktime":"30", + "ac_nk":"96,5" }, "KMD": { "rpc_user": "test", diff --git a/qa/pytest_komodo/ci_set_dex.sh b/qa/pytest_komodo/ci_set_dex.sh index c620f1b4c89..644d5025c18 100755 --- a/qa/pytest_komodo/ci_set_dex.sh +++ b/qa/pytest_komodo/ci_set_dex.sh @@ -3,18 +3,18 @@ # chains start script params export CLIENTS=2 export CHAIN="TONYCI" -export TEST_ADDY0="RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein" -export TEST_WIF0="UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr" -export TEST_PUBKEY0="02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9" +export TEST_ADDY0="RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd" +export TEST_WIF0="UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN" +export TEST_PUBKEY0="02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7" export TEST_ADDY1="RHoTHYiHD8TU4k9rbY4Aoj3ztxUARMJikH" export TEST_WIF1="UwmmwgfXwZ673brawUarPzbtiqjsCPWnG311ZRAL4iUCZLBLYeDu" export TEST_PUBKEY1="0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149" -export TEST_ADDY2="RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd" -export TEST_WIF2="UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN" -export TEST_PUBKEY2="02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7" +export TEST_ADDY2="RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein" +export TEST_WIF2="UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr" +export TEST_PUBKEY2="02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9" export CHAIN_MODE="DEX2" export IS_BOOTSTRAP_NEEDED="True" -export BOOTSTRAP_URL="https://sirseven.me/share/bootstrap4.tar.gz" +export BOOTSTRAP_URL="https://sirseven.me/share/bootstrap.tar.gz" # starting the chains python3 chainstart.py diff --git a/qa/pytest_komodo/ci_setup.sh b/qa/pytest_komodo/ci_setup.sh index 72939bde3ca..0fb5807a960 100755 --- a/qa/pytest_komodo/ci_setup.sh +++ b/qa/pytest_komodo/ci_setup.sh @@ -3,15 +3,15 @@ # chains start script params export CLIENTS=2 export CHAIN="TONYCI" -export TEST_ADDY0="RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein" -export TEST_WIF0="UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr" -export TEST_PUBKEY0="02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9" +export TEST_ADDY0="RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd" +export TEST_WIF0="UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN" +export TEST_PUBKEY0="02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7" export TEST_ADDY1="RHoTHYiHD8TU4k9rbY4Aoj3ztxUARMJikH" export TEST_WIF1="UwmmwgfXwZ673brawUarPzbtiqjsCPWnG311ZRAL4iUCZLBLYeDu" export TEST_PUBKEY1="0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149" export CHAIN_MODE="REGULAR" export IS_BOOTSTRAP_NEEDED="True" -export BOOTSTRAP_URL="https://sirseven.me/share/bootstrap4.tar.gz" +export BOOTSTRAP_URL="https://sirseven.me/share/bootstrap.tar.gz" # starting the chains python3 chainstart.py diff --git a/qa/pytest_komodo/conftest.py b/qa/pytest_komodo/conftest.py index a98a46f962e..17fbb009cbb 100644 --- a/qa/pytest_komodo/conftest.py +++ b/qa/pytest_komodo/conftest.py @@ -2,9 +2,8 @@ import json import os import time +from lib.komodo_requests import Proxy from lib.pytest_util import OraclesCC, TokenCC, DiceCC, ChannelsCC, RewardsCC -from slickrpc import Proxy - @pytest.fixture(scope='session') def proxy_connection(): @@ -12,10 +11,7 @@ def proxy_connection(): def _proxy_connection(node_params_dictionary): try: - proxy = Proxy("http://%s:%s@%s:%d" % (node_params_dictionary["rpc_user"], - node_params_dictionary["rpc_password"], - node_params_dictionary["rpc_ip"], - node_params_dictionary["rpc_port"]), timeout=360) + proxy = Proxy((node_params_dictionary), timeout=360) proxy_connected.append(proxy) except ConnectionAbortedError as e: raise Exception("Connection error! Probably no daemon on selected port. Error: ", e) diff --git a/qa/pytest_komodo/lib/komodo_requests.py b/qa/pytest_komodo/lib/komodo_requests.py new file mode 100644 index 00000000000..1a761d4e576 --- /dev/null +++ b/qa/pytest_komodo/lib/komodo_requests.py @@ -0,0 +1,39 @@ +# loosesly based on slick-bitcoinrpc https://github.com/barjomet/slick-bitcoinrpc/blob/master/slickrpc/rpc.py +import requests +from itertools import count +import ujson + +DEFAULT_HTTP_TIMEOUT = 120 +DEFAULT_RPC_PORT = 7777 + + +class Proxy: + _ids = count(0) + + def __init__(self, conf_dict: dict, timeout=DEFAULT_HTTP_TIMEOUT): + self.timeout = timeout + self.config = conf_dict + if not self.config.get('rpc_port'): + self.config['rpc_port'] = DEFAULT_RPC_PORT + + def __getattr__(self, req): + _id = next(self._ids) + + def call(*params): + post_val = { + 'jsonrpc': '2.0', + 'method': req, + 'params': params, + 'id': _id + } + url = 'http://%s:%s@%s:%s' % (self.config['rpc_user'], self.config['rpc_password'], self.config['rpc_ip'], self.config['rpc_port']) + post_data = ujson.dumps(post_val) + try: + resp = requests.post(url, data=post_data, timeout=self.timeout).json() + return resp['result'] + except ValueError: + resp = str(requests.post(url, data=post_data, timeout=self.timeout).content()) + print(resp) + return resp + + return call diff --git a/qa/pytest_komodo/lib/pytest_util.py b/qa/pytest_komodo/lib/pytest_util.py index dda063e752f..e0244892589 100644 --- a/qa/pytest_komodo/lib/pytest_util.py +++ b/qa/pytest_komodo/lib/pytest_util.py @@ -6,10 +6,7 @@ import hashlib import re import requests -from slickrpc import Proxy -from slickrpc.exc import RpcException as RPCError -from pycurl import error as HttpError - +from lib.komodo_requests import Proxy class CCInstance: def __init__(self, test_params: dict): @@ -265,10 +262,7 @@ def create_entropy(proxy, casino): def create_proxy(node_params_dictionary): try: - proxy = Proxy("http://%s:%s@%s:%d" % (node_params_dictionary.get('rpc_user'), - node_params_dictionary.get('rpc_password'), - node_params_dictionary.get('rpc_ip'), - node_params_dictionary.get('rpc_port')), timeout=120) + proxy = Proxy(node_params_dictionary, timeout=120) except Exception as e: raise Exception("Connection error! Probably no daemon on selected port. Error: ", e) return proxy @@ -362,7 +356,7 @@ def enable_mining(proxy): try: proxy.setgenerate(True, threads_count) break - except (RPCError, HttpError) as e: + except Exception as e: print(e, " Waiting chain startup\n") time.sleep(10) tries += 1 diff --git a/qa/pytest_komodo/lib/util.py b/qa/pytest_komodo/lib/util.py index 60f8a018ff4..7d5f9adeacd 100644 --- a/qa/pytest_komodo/lib/util.py +++ b/qa/pytest_komodo/lib/util.py @@ -3,7 +3,7 @@ import sys from random import choice from string import ascii_uppercase -from slickrpc import Proxy +from lib.komodo_requests import Proxy def assert_success(result): diff --git a/qa/pytest_komodo/nodesconfig.json b/qa/pytest_komodo/nodesconfig.json index 5b5aedac64e..ec328581cc9 100644 --- a/qa/pytest_komodo/nodesconfig.json +++ b/qa/pytest_komodo/nodesconfig.json @@ -5,9 +5,9 @@ "rpc_ip" : "127.0.0.1", "rpc_port": 7000, "net_port": 6000, - "pubkey" : "02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9", - "address": "RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein", - "txid": "3376a48a7daf543d8401e072102d4e93f53f300a101bd67e82820d2da0f2729e" + "pubkey" : "02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7", + "address": "RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd", + "txid": "e9945094eb1a9028afd310719aea21966425ceccc3f8c0972277a96201ca1b81" }, "node2" : { "rpc_user" : "test", @@ -17,7 +17,7 @@ "net_port": 6001, "pubkey" : "0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149", "address": "RHoTHYiHD8TU4k9rbY4Aoj3ztxUARMJikH", - "txid": "3376a48a7daf543d8401e072102d4e93f53f300a101bd67e82820d2da0f2729e" + "txid": "e9945094eb1a9028afd310719aea21966425ceccc3f8c0972277a96201ca1b81" }, "node3" : { "rpc_user" : "test", @@ -25,8 +25,8 @@ "rpc_ip" : "127.0.0.1", "rpc_port": 7002, "net_port": 6002, - "pubkey" : "02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7", - "address": "RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd", + "pubkey" : "02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9", + "address": "RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein", "txid": "e9945094eb1a9028afd310719aea21966425ceccc3f8c0972277a96201ca1b81" }, "is_fresh_chain": true diff --git a/qa/pytest_komodo/start_ci.bat b/qa/pytest_komodo/start_ci.bat index 31fdb27ae30..ad430fd23d5 100644 --- a/qa/pytest_komodo/start_ci.bat +++ b/qa/pytest_komodo/start_ci.bat @@ -1,14 +1,14 @@ set CLIENTS=2 set CHAIN=TONYCI -set TEST_ADDY0=RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein -set TEST_WIF0=UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr -set TEST_PUBKEY0=02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9 +set TEST_ADDY0=RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd +set TEST_WIF0=UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN +set TEST_PUBKEY0=02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7 set TEST_ADDY1=RHoTHYiHD8TU4k9rbY4Aoj3ztxUARMJikH set TEST_WIF1=UwmmwgfXwZ673brawUarPzbtiqjsCPWnG311ZRAL4iUCZLBLYeDu set TEST_PUBKEY1=0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149 set CHAIN_MODE=REGULAR set IS_BOOTSTRAP_NEEDED=True -set BOOTSTRAP_URL=https://sirseven.me/share/bootstrap4.tar.gz +set BOOTSTRAP_URL=https://sirseven.me/share/bootstrap.tar.gz python.exe chainstart.py diff --git a/qa/pytest_komodo/start_set_dex.bat b/qa/pytest_komodo/start_set_dex.bat index 2131d876ed1..acf88c2e6b2 100644 --- a/qa/pytest_komodo/start_set_dex.bat +++ b/qa/pytest_komodo/start_set_dex.bat @@ -1,17 +1,17 @@ set CLIENTS=2 set CHAIN=TONYCI -set TEST_ADDY0=RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein -set TEST_WIF0=UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr -set TEST_PUBKEY0=02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9 +set TEST_ADDY0=RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd +set TEST_WIF0=UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN +set TEST_PUBKEY0=02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7 set TEST_ADDY1=RHoTHYiHD8TU4k9rbY4Aoj3ztxUARMJikH set TEST_WIF1=UwmmwgfXwZ673brawUarPzbtiqjsCPWnG311ZRAL4iUCZLBLYeDu set TEST_PUBKEY1=0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149 -set TEST_ADDY2=RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd -set TEST_WIF2=UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN -set TEST_PUBKEY2=02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7 +set TEST_ADDY2=RB6fgrPX4ANGTtMUVud6aRh5cFy7TqVein +set TEST_WIF2=UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr +set TEST_PUBKEY2=02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9 set CHAIN_MODE=DEX2 set IS_BOOTSTRAP_NEEDED=True -set BOOTSTRAP_URL=https://sirseven.me/share/bootstrap4.tar.gz +set BOOTSTRAP_URL=https://sirseven.me/share/bootstrap.tar.gz python.exe chainstart.py From 602698186112831d2d15229f01eb968d72d52ee7 Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Fri, 24 Feb 2023 19:43:22 +0300 Subject: [PATCH 03/13] pytests: update bootstrap --- qa/pytest_komodo/ci_set_dex.sh | 2 +- qa/pytest_komodo/ci_setup.sh | 4 ++-- qa/pytest_komodo/nodesconfig.json | 4 ++-- qa/pytest_komodo/start_ci.bat | 4 ++-- qa/pytest_komodo/start_set_dex.bat | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/qa/pytest_komodo/ci_set_dex.sh b/qa/pytest_komodo/ci_set_dex.sh index 644d5025c18..96aaaf395ca 100755 --- a/qa/pytest_komodo/ci_set_dex.sh +++ b/qa/pytest_komodo/ci_set_dex.sh @@ -14,7 +14,7 @@ export TEST_WIF2="UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr" export TEST_PUBKEY2="02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9" export CHAIN_MODE="DEX2" export IS_BOOTSTRAP_NEEDED="True" -export BOOTSTRAP_URL="https://sirseven.me/share/bootstrap.tar.gz" +export BOOTSTRAP_URL="https://node.sirseven.me/fast_bootstrap.tar.gz" # starting the chains python3 chainstart.py diff --git a/qa/pytest_komodo/ci_setup.sh b/qa/pytest_komodo/ci_setup.sh index 0fb5807a960..791e28b561a 100755 --- a/qa/pytest_komodo/ci_setup.sh +++ b/qa/pytest_komodo/ci_setup.sh @@ -2,7 +2,7 @@ # chains start script params export CLIENTS=2 -export CHAIN="TONYCI" +export CHAIN="KMDCI" export TEST_ADDY0="RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd" export TEST_WIF0="UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN" export TEST_PUBKEY0="02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7" @@ -11,7 +11,7 @@ export TEST_WIF1="UwmmwgfXwZ673brawUarPzbtiqjsCPWnG311ZRAL4iUCZLBLYeDu" export TEST_PUBKEY1="0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149" export CHAIN_MODE="REGULAR" export IS_BOOTSTRAP_NEEDED="True" -export BOOTSTRAP_URL="https://sirseven.me/share/bootstrap.tar.gz" +export BOOTSTRAP_URL="https://node.sirseven.me/fast_bootstrap.tar.gz" # starting the chains python3 chainstart.py diff --git a/qa/pytest_komodo/nodesconfig.json b/qa/pytest_komodo/nodesconfig.json index ec328581cc9..a2bdca95779 100644 --- a/qa/pytest_komodo/nodesconfig.json +++ b/qa/pytest_komodo/nodesconfig.json @@ -7,7 +7,7 @@ "net_port": 6000, "pubkey" : "02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7", "address": "RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd", - "txid": "e9945094eb1a9028afd310719aea21966425ceccc3f8c0972277a96201ca1b81" + "txid": "e4dc1e30f0f5b970c50364126110b8468209616584570a03ae0c2a5f1ad4903f" }, "node2" : { "rpc_user" : "test", @@ -17,7 +17,7 @@ "net_port": 6001, "pubkey" : "0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149", "address": "RHoTHYiHD8TU4k9rbY4Aoj3ztxUARMJikH", - "txid": "e9945094eb1a9028afd310719aea21966425ceccc3f8c0972277a96201ca1b81" + "txid": "cdd16c5760fe6b73e65365f06a0020df4f2827469fa1d8dbd374a181996b2235" }, "node3" : { "rpc_user" : "test", diff --git a/qa/pytest_komodo/start_ci.bat b/qa/pytest_komodo/start_ci.bat index ad430fd23d5..00b887898c6 100644 --- a/qa/pytest_komodo/start_ci.bat +++ b/qa/pytest_komodo/start_ci.bat @@ -1,5 +1,5 @@ set CLIENTS=2 -set CHAIN=TONYCI +set CHAIN=KMDCI set TEST_ADDY0=RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd set TEST_WIF0=UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN set TEST_PUBKEY0=02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7 @@ -8,7 +8,7 @@ set TEST_WIF1=UwmmwgfXwZ673brawUarPzbtiqjsCPWnG311ZRAL4iUCZLBLYeDu set TEST_PUBKEY1=0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149 set CHAIN_MODE=REGULAR set IS_BOOTSTRAP_NEEDED=True -set BOOTSTRAP_URL=https://sirseven.me/share/bootstrap.tar.gz +set BOOTSTRAP_URL=https://node.sirseven.me/fast_bootstrap.tar.gz python.exe chainstart.py diff --git a/qa/pytest_komodo/start_set_dex.bat b/qa/pytest_komodo/start_set_dex.bat index acf88c2e6b2..774b5379e10 100644 --- a/qa/pytest_komodo/start_set_dex.bat +++ b/qa/pytest_komodo/start_set_dex.bat @@ -1,5 +1,5 @@ set CLIENTS=2 -set CHAIN=TONYCI +set CHAIN=KMDCI set TEST_ADDY0=RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd set TEST_WIF0=UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN set TEST_PUBKEY0=02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7 @@ -11,7 +11,7 @@ set TEST_WIF2=UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr set TEST_PUBKEY2=02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9 set CHAIN_MODE=DEX2 set IS_BOOTSTRAP_NEEDED=True -set BOOTSTRAP_URL=https://sirseven.me/share/bootstrap.tar.gz +set BOOTSTRAP_URL=https://node.sirseven.me/fast_bootstrap.tar.gz python.exe chainstart.py From 00ca66190ed0c063ce0b370ed328b9d48760c34a Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Fri, 24 Feb 2023 19:57:45 +0300 Subject: [PATCH 04/13] Workflow: Use requests instead of slickrpc, formatting, remove unnecessary apt upgrades --- .github/workflows/komodo_linux_ci.yml | 61 ++++++++++++--------------- .github/workflows/komodo_mac_ci.yml | 14 +++--- .github/workflows/komodo_win_ci.yml | 24 +++++++---- .github/workflows/komodod_cd.yml | 20 ++++++--- 4 files changed, 64 insertions(+), 55 deletions(-) diff --git a/.github/workflows/komodo_linux_ci.yml b/.github/workflows/komodo_linux_ci.yml index a1c27e2e81d..f2e7bde47fc 100644 --- a/.github/workflows/komodo_linux_ci.yml +++ b/.github/workflows/komodo_linux_ci.yml @@ -20,26 +20,18 @@ jobs: env: DEBIAN_FRONTEND: noninteractive run: | - sudo apt-get update # prevents repo404 errors on apt-remove below - sudo apt-get remove php* msodbcsql17 mysql* powershell dotn* sudo apt-get update - sudo ACCEPT_EULA=Y apt-get upgrade -y sudo apt-get install -q \ curl \ - python3 \ - python3-dev \ - python3-setuptools \ - python3-pip \ libcurl4-openssl-dev \ libssl-dev -y - python3 -m pip install setuptools wheel - python3 -m pip install pytest wget jsonschema - python3 -m pip install -Iv https://github.com/KomodoPlatform/slick-bitcoinrpc/archive/refs/tags/0.1.4.tar.gz + - name: Build (Linux) run: | # flag for some CC tests transactions - so DO NOT USE THIS CI ARTIFACTS IN PRODUCTION!!! CONFIGURE_FLAGS='CPPFLAGS=-DTESTMODE' ./zcutil/build.sh -j$(nproc) tar -czvf komodo-linux.tar.gz src/komodod src/komodo-cli + - name: Upload komodo-linux.tar.gz as artifact uses: actions/upload-artifact@v1 with: @@ -63,12 +55,11 @@ jobs: python3 \ python3-dev \ python3-setuptools \ - python3-pip \ - libcurl4-openssl-dev \ - libssl-dev -y - python3 -m pip install setuptools wheel + python3-pip + python3 -m pip install wheel python3 -m pip install pytest wget jsonschema - python3 -m pip install -Iv https://github.com/KomodoPlatform/slick-bitcoinrpc/archive/refs/tags/0.1.4.tar.gz + python3 -m pip install requests + - name: Download komodo-linux.tar.gz uses: actions/download-artifact@v1 with: @@ -82,6 +73,7 @@ jobs: ./zcutil/fetch-params.sh cd qa/pytest_komodo ./ci_setup.sh "cc_modules/test_dice.py cc_modules/test_faucet.py cc_modules/test_token.py cc_modules/test_rewards.py" + linux-test-oracles: name: Test (Linux/OraclesCC) @@ -99,12 +91,11 @@ jobs: python3 \ python3-dev \ python3-setuptools \ - python3-pip \ - libcurl4-openssl-dev \ - libssl-dev -y - python3 -m pip install setuptools wheel + python3-pip + python3 -m pip install wheel python3 -m pip install pytest wget jsonschema - python3 -m pip install -Iv https://github.com/KomodoPlatform/slick-bitcoinrpc/archive/refs/tags/0.1.4.tar.gz + python3 -m pip install requests + - name: Download komodo-linux.tar.gz uses: actions/download-artifact@v1 with: @@ -118,6 +109,7 @@ jobs: ./zcutil/fetch-params.sh cd qa/pytest_komodo ./ci_setup.sh cc_modules/test_oracles.py + linux-test-baserpc: name: Test (Linux/BasicRPC) @@ -135,12 +127,11 @@ jobs: python3 \ python3-dev \ python3-setuptools \ - python3-pip \ - libcurl4-openssl-dev \ - libssl-dev -y - python3 -m pip install setuptools wheel + python3-pip + python3 -m pip install wheel python3 -m pip install pytest wget jsonschema - python3 -m pip install -Iv https://github.com/KomodoPlatform/slick-bitcoinrpc/archive/refs/tags/0.1.4.tar.gz + python3 -m pip install requests + - name: Download komodo-linux.tar.gz uses: actions/download-artifact@v1 with: @@ -154,6 +145,7 @@ jobs: ./zcutil/fetch-params.sh cd qa/pytest_komodo ./ci_setup.sh basic + linux-test-channels: name: Test (Linux/ChannelsCC) @@ -171,12 +163,11 @@ jobs: python3 \ python3-dev \ python3-setuptools \ - python3-pip \ - libcurl4-openssl-dev \ - libssl-dev -y - python3 -m pip install setuptools wheel + python3-pip + python3 -m pip install wheel python3 -m pip install pytest wget jsonschema - python3 -m pip install -Iv https://github.com/KomodoPlatform/slick-bitcoinrpc/archive/refs/tags/0.1.4.tar.gz + python3 -m pip install requests + - name: Download komodo-linux.tar.gz uses: actions/download-artifact@v1 with: @@ -190,6 +181,7 @@ jobs: ./zcutil/fetch-params.sh cd qa/pytest_komodo ./ci_setup.sh cc_modules/test_channels.py + linux-test-heir: name: Test (Linux/HeirCC) @@ -207,12 +199,11 @@ jobs: python3 \ python3-dev \ python3-setuptools \ - python3-pip \ - libcurl4-openssl-dev \ - libssl-dev -y - python3 -m pip install setuptools wheel + python3-pip + python3 -m pip install wheel python3 -m pip install pytest wget jsonschema - python3 -m pip install -Iv https://github.com/KomodoPlatform/slick-bitcoinrpc/archive/refs/tags/0.1.4.tar.gz + python3 -m pip install requests + - name: Download komodo-linux.tar.gz uses: actions/download-artifact@v1 with: diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index 1c25dbce07a..0c8445cfb6f 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -55,7 +55,7 @@ jobs: run: | brew install python3 curl python3 -m pip install setuptools wheel - python3 -m pip install slick-bitcoinrpc pytest wget jsonschema + python3 -m pip install requests pytest wget jsonschema - name: Download komodo-macos.tar.gz uses: actions/download-artifact@v1 @@ -84,7 +84,8 @@ jobs: run: | brew install python3 curl python3 -m pip install setuptools wheel - python3 -m pip install slick-bitcoinrpc pytest wget jsonschema + python3 -m pip install requests pytest wget jsonschema + - name: Download komodo-macos.tar.gz uses: actions/download-artifact@v1 with: @@ -112,7 +113,8 @@ jobs: run: | brew install python3 curl python3 -m pip install setuptools wheel - python3 -m pip install slick-bitcoinrpc pytest wget jsonschema + python3 -m pip install requests pytest wget jsonschema + - name: Download komodo-macos.tar.gz uses: actions/download-artifact@v1 with: @@ -140,7 +142,8 @@ jobs: run: | brew install python3 curl python3 -m pip install setuptools wheel - python3 -m pip install slick-bitcoinrpc pytest wget jsonschema + python3 -m pip install requests pytest wget jsonschema + - name: Download komodo-macos.tar.gz uses: actions/download-artifact@v1 with: @@ -168,7 +171,8 @@ jobs: run: | brew install python3 curl python3 -m pip install setuptools wheel - python3 -m pip install slick-bitcoinrpc pytest wget jsonschema + python3 -m pip install requests pytest wget jsonschema + - name: Download komodo-macos.tar.gz uses: actions/download-artifact@v1 with: diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index e1e100a8cfd..00b7651f37c 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -20,9 +20,6 @@ jobs: DEBIAN_FRONTEND: noninteractive run: | sudo apt-get update # prevents repo404 errors on apt-remove below - sudo apt-get remove php* msodbcsql17 mysql* powershell containernetworking-* containers* dotn* - sudo ACCEPT_EULA=Y apt-get upgrade -y - sudo apt-get update sudo apt-get install build-essential \ pkg-config \ libc6-dev \ @@ -60,12 +57,14 @@ jobs: rustup target add x86_64-pc-windows-gnu sudo update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix + - name: Build Win (mingw) run: | # flag for some CC tests transactions - so DO NOT USE THIS CI ARTIFACTS IN PRODUCTION!!! export CONFIGURE_FLAGS='CPPFLAGS=-DTESTMODE' ./zcutil/build-win-dtest.sh -j$(nproc) zip --junk-paths komodod_win src/komodod.exe src/komodo-cli.exe + - name: Upload komodod.exe as artifact uses: actions/upload-artifact@v1 with: @@ -95,13 +94,15 @@ jobs: python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install slick-bitcoinrpc + python.exe -m pip install requests zcutil\fetch-params.bat + - name: Base RPC Test (Windows) shell: cmd run: | cd qa\pytest_komodo start_ci.bat basic + windows-test-dice-faucet-tok-rewCC: name: Test (Win/Dice Faucet Token Rewards) @@ -125,13 +126,15 @@ jobs: python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install slick-bitcoinrpc + python.exe -m pip install requests zcutil\fetch-params.bat + - name: CC Dice Faucet Tokens Rewards (Windows) shell: cmd run: | cd qa\pytest_komodo start_ci.bat cc_modules\test_dice.py cc_modules\test_faucet.py cc_modules\test_token.py cc_modules\test_rewards.py + windows-test-oracles-cc: name: Test (Win/OraclesCC) @@ -155,13 +158,15 @@ jobs: python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install slick-bitcoinrpc + python.exe -m pip install requests zcutil\fetch-params.bat + - name: CC Oracles (Windows) shell: cmd run: | cd qa\pytest_komodo start_ci.bat cc_modules\test_oracles.py + windows-test-heir-cc: name: Test (Win/HeirCC) @@ -185,13 +190,15 @@ jobs: python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install slick-bitcoinrpc + python.exe -m pip install requests zcutil\fetch-params.bat + - name: CC Heir (Windows) shell: cmd run: | cd qa\pytest_komodo start_ci.bat cc_modules\test_heir.py + windows-test-channels-cc: name: Test (Win/ChannelsCC) @@ -215,8 +222,9 @@ jobs: python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install slick-bitcoinrpc + python.exe -m pip install requests zcutil\fetch-params.bat + - name: ChannelsCC (Windows) shell: cmd run: | diff --git a/.github/workflows/komodod_cd.yml b/.github/workflows/komodod_cd.yml index 6e97169e049..842e4cf0a5a 100644 --- a/.github/workflows/komodod_cd.yml +++ b/.github/workflows/komodod_cd.yml @@ -8,7 +8,6 @@ on: branches: - beta - dev - - research jobs: @@ -34,10 +33,7 @@ jobs: - name: Install deps (Linux) run: | - sudo apt-get update # prevents repo404 errors on apt-remove below - sudo apt-get remove php* msodbcsql17 mysql* powershell dotn* sudo apt-get update - sudo ACCEPT_EULA=Y apt-get upgrade -y sudo apt-get install -q \ curl \ python3 \ @@ -46,11 +42,13 @@ jobs: python3-pip \ libcurl4-openssl-dev \ libssl-dev -y + - name: Build (Linux) if: runner.os == 'Linux' run: | ./zcutil/build.sh -j$(nproc) zip --junk-paths komodo-linux src/komodod src/komodo-cli + - name: Upload komodo-linux.zip as artifact uses: actions/upload-artifact@v1 with: @@ -75,6 +73,7 @@ jobs: name: OSX Build runs-on: macos-latest steps: + - uses: actions/checkout@v2 - name: Install deps (macOS) run: | @@ -89,10 +88,12 @@ jobs: brew install wget brew install python3 brew install gmp + - name: Build (macOS) run: | ./zcutil/build-mac.sh -j4 zip --junk-paths komodo-osx src/komodod src/komodo-cli + - name: Upload komodo-osx.zip as artifact uses: actions/upload-artifact@v1 with: @@ -109,10 +110,7 @@ jobs: env: DEBIAN_FRONTEND: noninteractive run: | - sudo apt-get update # prevents repo404 errors on apt-remove below - sudo apt-get remove php* msodbcsql17 mysql* powershell containernetworking-* containers* dotn* sudo apt-get update - sudo apt-get upgrade -y sudo apt-get install build-essential pkg-config libc6-dev m4 g++-multilib autoconf libtool \ libncurses-dev unzip wget bsdmainutils automake libboost-all-dev libssl-dev \ libprotobuf-dev protobuf-compiler libqrencode-dev libdb++-dev ntp ntpdate nano \ @@ -123,10 +121,12 @@ jobs: rustup target add x86_64-pc-windows-gnu sudo update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix + - name: Build (Windows) run: | ./zcutil/build-win.sh -j$(nproc) zip --junk-paths komodo-win src/komodod.exe src/komodo-cli.exe + - name: Upload komodo-win.zip as artifact uses: actions/upload-artifact@v1 with: @@ -138,14 +138,17 @@ jobs: runs-on: ubuntu-latest needs: [linux-build, osx-build, windows-build] steps: + - name: Download komodo-linux.zip uses: actions/download-artifact@v1 with: name: komodo-linux + - name: Download komodo-osx.zip uses: actions/download-artifact@v1 with: name: komodo-osx + - name: Download komodo-win.zip uses: actions/download-artifact@v1 with: @@ -171,6 +174,7 @@ jobs: release_name: CD Release ${{ steps.shortify_commit.outputs.sha_short }} ${{ steps.extract_branch.outputs.branch }} draft: false prerelease: true + - name: Upload Linux Release Asset id: upload-linux-release-asset uses: actions/upload-release-asset@latest @@ -181,6 +185,7 @@ jobs: asset_path: komodo-linux/komodo-linux.zip asset_name: komodo_${{ steps.shortify_commit.outputs.sha_short }}_${{ steps.extract_branch.outputs.branch }}_linux.zip asset_content_type: application/zip + - name: Upload OSX Release Asset id: upload-osx-release-asset uses: actions/upload-release-asset@latest @@ -191,6 +196,7 @@ jobs: asset_path: komodo-osx/komodo-osx.zip asset_name: komodo_${{ steps.shortify_commit.outputs.sha_short }}_${{ steps.extract_branch.outputs.branch }}_osx.zip asset_content_type: application/zip + - name: Upload Windows Release Asset id: upload-windows-release-asset uses: actions/upload-release-asset@latest From 06681367606922dc5bb8c691749b81e3731177e5 Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Fri, 24 Feb 2023 20:25:10 +0300 Subject: [PATCH 05/13] Workflow: deps change --- .github/workflows/komodo_linux_ci.yml | 25 ++++++++++++++++++++++--- .github/workflows/komodo_win_ci.yml | 26 ++++++++------------------ 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/.github/workflows/komodo_linux_ci.yml b/.github/workflows/komodo_linux_ci.yml index f2e7bde47fc..7a1dfdc5306 100644 --- a/.github/workflows/komodo_linux_ci.yml +++ b/.github/workflows/komodo_linux_ci.yml @@ -22,9 +22,28 @@ jobs: run: | sudo apt-get update sudo apt-get install -q \ - curl \ - libcurl4-openssl-dev \ - libssl-dev -y + build-essential \ + pkg-config \ + libc6-dev \ + m4 \ + g++-multilib \ + autoconf \ + libtool \ + ncurses-dev \ + unzip \ + git \ + python3 \ + python3-zmq \ + zlib1g-dev \ + wget \ + libcurl4-gnutls-dev \ + bsdmainutils \ + automake \ + curl \ + cmake \ + mingw-w64 \ + libsodium-dev \ + libevent-dev -y - name: Build (Linux) run: | diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 00b7651f37c..047077e8d6c 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -25,33 +25,23 @@ jobs: libc6-dev \ m4 \ g++-multilib \ - autoconf libtool \ - libncurses-dev \ - unzip \ + autoconf \ + libtool \ + ncurses-dev \ + unzip \ git \ python3 \ + python3-zmq \ zlib1g-dev \ wget \ + libcurl4-gnutls-dev \ bsdmainutils \ automake \ - libboost-all-dev \ - libssl-dev \ - libprotobuf-dev \ - protobuf-compiler \ - libqrencode-dev \ - libdb++-dev \ - ntp \ - ntpdate \ - nano \ - software-properties-common \ curl \ - libevent-dev \ - libcurl4-gnutls-dev \ cmake \ - clang \ + mingw-w64 \ libsodium-dev \ - python3-zmq \ - mingw-w64 -y + libevent-dev -y curl https://sh.rustup.rs -sSf | sh -s -- -y source $HOME/.cargo/env rustup target add x86_64-pc-windows-gnu From e7e33640eaa9130055653b38a01a81be0e731ecc Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Fri, 24 Feb 2023 20:33:13 +0300 Subject: [PATCH 06/13] Workflow: pip deps --- .github/workflows/komodo_linux_ci.yml | 10 +++++----- .github/workflows/komodo_mac_ci.yml | 10 +++++----- .github/workflows/komodo_win_ci.yml | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/komodo_linux_ci.yml b/.github/workflows/komodo_linux_ci.yml index 7a1dfdc5306..0d31525a2c1 100644 --- a/.github/workflows/komodo_linux_ci.yml +++ b/.github/workflows/komodo_linux_ci.yml @@ -77,7 +77,7 @@ jobs: python3-pip python3 -m pip install wheel python3 -m pip install pytest wget jsonschema - python3 -m pip install requests + python3 -m pip install requests ujson - name: Download komodo-linux.tar.gz uses: actions/download-artifact@v1 @@ -113,7 +113,7 @@ jobs: python3-pip python3 -m pip install wheel python3 -m pip install pytest wget jsonschema - python3 -m pip install requests + python3 -m pip install requests ujson - name: Download komodo-linux.tar.gz uses: actions/download-artifact@v1 @@ -149,7 +149,7 @@ jobs: python3-pip python3 -m pip install wheel python3 -m pip install pytest wget jsonschema - python3 -m pip install requests + python3 -m pip install requests ujson - name: Download komodo-linux.tar.gz uses: actions/download-artifact@v1 @@ -185,7 +185,7 @@ jobs: python3-pip python3 -m pip install wheel python3 -m pip install pytest wget jsonschema - python3 -m pip install requests + python3 -m pip install requests ujson - name: Download komodo-linux.tar.gz uses: actions/download-artifact@v1 @@ -221,7 +221,7 @@ jobs: python3-pip python3 -m pip install wheel python3 -m pip install pytest wget jsonschema - python3 -m pip install requests + python3 -m pip install requests ujson - name: Download komodo-linux.tar.gz uses: actions/download-artifact@v1 diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index 0c8445cfb6f..5d431ffb498 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -55,7 +55,7 @@ jobs: run: | brew install python3 curl python3 -m pip install setuptools wheel - python3 -m pip install requests pytest wget jsonschema + python3 -m pip install requests pytest wget jsonschema ujson - name: Download komodo-macos.tar.gz uses: actions/download-artifact@v1 @@ -84,7 +84,7 @@ jobs: run: | brew install python3 curl python3 -m pip install setuptools wheel - python3 -m pip install requests pytest wget jsonschema + python3 -m pip install requests pytest wget jsonschema ujson - name: Download komodo-macos.tar.gz uses: actions/download-artifact@v1 @@ -113,7 +113,7 @@ jobs: run: | brew install python3 curl python3 -m pip install setuptools wheel - python3 -m pip install requests pytest wget jsonschema + python3 -m pip install requests pytest wget jsonschema ujson - name: Download komodo-macos.tar.gz uses: actions/download-artifact@v1 @@ -142,7 +142,7 @@ jobs: run: | brew install python3 curl python3 -m pip install setuptools wheel - python3 -m pip install requests pytest wget jsonschema + python3 -m pip install requests pytest wget jsonschema ujson - name: Download komodo-macos.tar.gz uses: actions/download-artifact@v1 @@ -171,7 +171,7 @@ jobs: run: | brew install python3 curl python3 -m pip install setuptools wheel - python3 -m pip install requests pytest wget jsonschema + python3 -m pip install requests pytest wget jsonschema ujson - name: Download komodo-macos.tar.gz uses: actions/download-artifact@v1 diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 047077e8d6c..4b9ae4669a0 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -84,7 +84,7 @@ jobs: python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install requests + python.exe -m pip install requests ujson zcutil\fetch-params.bat - name: Base RPC Test (Windows) @@ -116,7 +116,7 @@ jobs: python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install requests + python.exe -m pip install requests ujson zcutil\fetch-params.bat - name: CC Dice Faucet Tokens Rewards (Windows) @@ -148,7 +148,7 @@ jobs: python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install requests + python.exe -m pip install requests ujson zcutil\fetch-params.bat - name: CC Oracles (Windows) @@ -180,7 +180,7 @@ jobs: python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install requests + python.exe -m pip install requests ujson zcutil\fetch-params.bat - name: CC Heir (Windows) @@ -212,7 +212,7 @@ jobs: python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip python.exe -m pip install pycurl pytest wget jsonschema - python.exe -m pip install requests + python.exe -m pip install requests ujson zcutil\fetch-params.bat - name: ChannelsCC (Windows) From b3a41d05de1fa3e3da13586b79b4d3f37fa7e845 Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Fri, 24 Feb 2023 20:43:29 +0300 Subject: [PATCH 07/13] Workflow: comment out mac CPATH --- .github/workflows/komodo_mac_ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index 5d431ffb498..bfa99d7e977 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -21,7 +21,7 @@ jobs: brew upgrade || true brew tap discoteq/discoteq; brew install flock brew install autoconf autogen automake - brew install gcc@8 + brew install gcc@9 brew install binutils brew install protobuf brew install coreutils @@ -32,7 +32,7 @@ jobs: - name: Build (macOS) run: | # flag for some CC tests transactions - so DO NOT USE THIS CI ARTIFACTS IN PRODUCTION!!! - export CPATH=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ + # export CPATH=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ ./zcutil/build-mac-dtest.sh -j4 tar -czvf komodo-macos.tar.gz src/komodod src/komodo-cli From 60b252faafde1f7040c9ba989c7c88da456e0300 Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Fri, 24 Feb 2023 22:58:42 +0300 Subject: [PATCH 08/13] Workflow: encomment CPATH, remove pycurl pip dep --- .github/workflows/komodo_mac_ci.yml | 2 +- .github/workflows/komodo_win_ci.yml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index bfa99d7e977..6b8c82e8f7f 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -32,7 +32,7 @@ jobs: - name: Build (macOS) run: | # flag for some CC tests transactions - so DO NOT USE THIS CI ARTIFACTS IN PRODUCTION!!! - # export CPATH=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ + export CPATH=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ ./zcutil/build-mac-dtest.sh -j4 tar -czvf komodo-macos.tar.gz src/komodod src/komodo-cli diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 4b9ae4669a0..1e2c9f05e47 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -83,7 +83,7 @@ jobs: move komodod.exe src\ python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip - python.exe -m pip install pycurl pytest wget jsonschema + python.exe -m pip install pytest wget jsonschema python.exe -m pip install requests ujson zcutil\fetch-params.bat @@ -115,7 +115,7 @@ jobs: move komodod.exe src\ python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip - python.exe -m pip install pycurl pytest wget jsonschema + python.exe -m pip install pytest wget jsonschema python.exe -m pip install requests ujson zcutil\fetch-params.bat @@ -147,7 +147,7 @@ jobs: move komodod.exe src\ python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip - python.exe -m pip install pycurl pytest wget jsonschema + python.exe -m pip install pytest wget jsonschema python.exe -m pip install requests ujson zcutil\fetch-params.bat @@ -179,7 +179,7 @@ jobs: move komodod.exe src\ python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip - python.exe -m pip install pycurl pytest wget jsonschema + python.exe -m pip install pytest wget jsonschema python.exe -m pip install requests ujson zcutil\fetch-params.bat @@ -211,7 +211,7 @@ jobs: move komodod.exe src\ python.exe -m pip install --upgrade setuptools python.exe -m pip install --upgrade pip - python.exe -m pip install pycurl pytest wget jsonschema + python.exe -m pip install pytest wget jsonschema python.exe -m pip install requests ujson zcutil\fetch-params.bat From c045bd0dfc834bbd935dad2c87f98980d5612b61 Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Fri, 24 Feb 2023 23:03:30 +0300 Subject: [PATCH 09/13] Workflow: update deprecated actions --- .github/workflows/komodo_linux_ci.yml | 12 ++++++------ .github/workflows/komodo_mac_ci.yml | 12 ++++++------ .github/workflows/komodo_win_ci.yml | 12 ++++++------ .github/workflows/komodod_cd.yml | 6 +++--- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/komodo_linux_ci.yml b/.github/workflows/komodo_linux_ci.yml index 0d31525a2c1..7170e543a29 100644 --- a/.github/workflows/komodo_linux_ci.yml +++ b/.github/workflows/komodo_linux_ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps (Linux) @@ -64,7 +64,7 @@ jobs: needs: linux-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps (Dice, Token, Faucet, Rewards CC) run: | @@ -100,7 +100,7 @@ jobs: needs: linux-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps (OraclesCC) run: | @@ -136,7 +136,7 @@ jobs: needs: linux-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps (BasicRPC) run: | @@ -172,7 +172,7 @@ jobs: needs: linux-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps (ChannelsCC) run: | @@ -208,7 +208,7 @@ jobs: needs: linux-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps (HeirCC) run: | diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index 6b8c82e8f7f..1235e95cc8f 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: macos-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps (macOS) run: | @@ -49,7 +49,7 @@ jobs: needs: macos-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps (Dice, Token, Faucet, Rewards CC) run: | @@ -78,7 +78,7 @@ jobs: needs: macos-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps (OraclesCC) run: | @@ -107,7 +107,7 @@ jobs: needs: macos-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps (BasicRPC) run: | @@ -136,7 +136,7 @@ jobs: needs: macos-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps (ChannelsCC) run: | @@ -165,7 +165,7 @@ jobs: needs: macos-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps (HeirCC) run: | diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 1e2c9f05e47..9beb8a0ca18 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps(mingw) env: DEBIAN_FRONTEND: noninteractive @@ -68,7 +68,7 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Download komodo_win.zip uses: actions/download-artifact@v1 @@ -100,7 +100,7 @@ jobs: needs: windows-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Download komodo_win.zip uses: actions/download-artifact@v1 @@ -132,7 +132,7 @@ jobs: needs: windows-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Download komodo_win.zip uses: actions/download-artifact@v1 @@ -164,7 +164,7 @@ jobs: needs: windows-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Download komodo_win.zip uses: actions/download-artifact@v1 @@ -196,7 +196,7 @@ jobs: needs: windows-build steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Download komodo_win.zip uses: actions/download-artifact@v1 diff --git a/.github/workflows/komodod_cd.yml b/.github/workflows/komodod_cd.yml index 842e4cf0a5a..a95d8ab5175 100644 --- a/.github/workflows/komodod_cd.yml +++ b/.github/workflows/komodod_cd.yml @@ -29,7 +29,7 @@ jobs: id: shortify_commit - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install deps (Linux) run: | @@ -74,7 +74,7 @@ jobs: runs-on: macos-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps (macOS) run: | brew update @@ -105,7 +105,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install deps (Windows) env: DEBIAN_FRONTEND: noninteractive From c131d20e475d27809decdb9281e0a2590b1e9143 Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Fri, 24 Feb 2023 23:05:59 +0300 Subject: [PATCH 10/13] Workflow: revert gcc version for mac --- .github/workflows/komodo_mac_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index 1235e95cc8f..0981b119f9f 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -21,7 +21,7 @@ jobs: brew upgrade || true brew tap discoteq/discoteq; brew install flock brew install autoconf autogen automake - brew install gcc@9 + brew install gcc@8 brew install binutils brew install protobuf brew install coreutils From bfe7442ae10a8ac59314dba81cf6016f57112373 Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Sat, 25 Feb 2023 16:47:52 +0300 Subject: [PATCH 11/13] Workflow: Up artifact actions version --- .github/workflows/komodo_linux_ci.yml | 12 ++++++------ .github/workflows/komodo_mac_ci.yml | 12 ++++++------ .github/workflows/komodo_win_ci.yml | 12 ++++++------ .github/workflows/komodod_cd.yml | 12 ++++++------ 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/komodo_linux_ci.yml b/.github/workflows/komodo_linux_ci.yml index 7170e543a29..5c431cfb647 100644 --- a/.github/workflows/komodo_linux_ci.yml +++ b/.github/workflows/komodo_linux_ci.yml @@ -52,7 +52,7 @@ jobs: tar -czvf komodo-linux.tar.gz src/komodod src/komodo-cli - name: Upload komodo-linux.tar.gz as artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v3 with: name: komodo-linux path: ./komodo-linux.tar.gz @@ -80,7 +80,7 @@ jobs: python3 -m pip install requests ujson - name: Download komodo-linux.tar.gz - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodo-linux @@ -116,7 +116,7 @@ jobs: python3 -m pip install requests ujson - name: Download komodo-linux.tar.gz - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodo-linux @@ -152,7 +152,7 @@ jobs: python3 -m pip install requests ujson - name: Download komodo-linux.tar.gz - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodo-linux @@ -188,7 +188,7 @@ jobs: python3 -m pip install requests ujson - name: Download komodo-linux.tar.gz - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodo-linux @@ -224,7 +224,7 @@ jobs: python3 -m pip install requests ujson - name: Download komodo-linux.tar.gz - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodo-linux diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index 0981b119f9f..5d1807def6d 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -37,7 +37,7 @@ jobs: tar -czvf komodo-macos.tar.gz src/komodod src/komodo-cli - name: Upload komodo-macos.tar.gz as artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v3 with: name: komodo-macos path: ./komodo-macos.tar.gz @@ -58,7 +58,7 @@ jobs: python3 -m pip install requests pytest wget jsonschema ujson - name: Download komodo-macos.tar.gz - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodo-macos @@ -87,7 +87,7 @@ jobs: python3 -m pip install requests pytest wget jsonschema ujson - name: Download komodo-macos.tar.gz - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodo-macos @@ -116,7 +116,7 @@ jobs: python3 -m pip install requests pytest wget jsonschema ujson - name: Download komodo-macos.tar.gz - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodo-macos @@ -145,7 +145,7 @@ jobs: python3 -m pip install requests pytest wget jsonschema ujson - name: Download komodo-macos.tar.gz - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodo-macos @@ -174,7 +174,7 @@ jobs: python3 -m pip install requests pytest wget jsonschema ujson - name: Download komodo-macos.tar.gz - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodo-macos diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index 9beb8a0ca18..da97e0406bd 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -56,7 +56,7 @@ jobs: zip --junk-paths komodod_win src/komodod.exe src/komodo-cli.exe - name: Upload komodod.exe as artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v3 with: name: komodod_win path: ./komodod_win.zip @@ -71,7 +71,7 @@ jobs: - uses: actions/checkout@v3 - name: Download komodo_win.zip - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodod_win @@ -103,7 +103,7 @@ jobs: - uses: actions/checkout@v3 - name: Download komodo_win.zip - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodod_win @@ -135,7 +135,7 @@ jobs: - uses: actions/checkout@v3 - name: Download komodo_win.zip - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodod_win @@ -167,7 +167,7 @@ jobs: - uses: actions/checkout@v3 - name: Download komodo_win.zip - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodod_win @@ -199,7 +199,7 @@ jobs: - uses: actions/checkout@v3 - name: Download komodo_win.zip - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodod_win diff --git a/.github/workflows/komodod_cd.yml b/.github/workflows/komodod_cd.yml index a95d8ab5175..78cd31ca2f1 100644 --- a/.github/workflows/komodod_cd.yml +++ b/.github/workflows/komodod_cd.yml @@ -50,7 +50,7 @@ jobs: zip --junk-paths komodo-linux src/komodod src/komodo-cli - name: Upload komodo-linux.zip as artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v3 with: name: komodo-linux path: ./komodo-linux.zip @@ -95,7 +95,7 @@ jobs: zip --junk-paths komodo-osx src/komodod src/komodo-cli - name: Upload komodo-osx.zip as artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v3 with: name: komodo-osx path: ./komodo-osx.zip @@ -128,7 +128,7 @@ jobs: zip --junk-paths komodo-win src/komodod.exe src/komodo-cli.exe - name: Upload komodo-win.zip as artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v3 with: name: komodo-win path: ./komodo-win.zip @@ -140,17 +140,17 @@ jobs: steps: - name: Download komodo-linux.zip - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodo-linux - name: Download komodo-osx.zip - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodo-osx - name: Download komodo-win.zip - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: name: komodo-win From 1a21aebf1a90a8bdfe1af22d8bae3e1c97d0fedb Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Sat, 25 Feb 2023 18:06:47 +0300 Subject: [PATCH 12/13] Workflow: fix access to linux artifacts --- .github/workflows/komodo_linux_ci.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/komodo_linux_ci.yml b/.github/workflows/komodo_linux_ci.yml index 5c431cfb647..c2cee7746b1 100644 --- a/.github/workflows/komodo_linux_ci.yml +++ b/.github/workflows/komodo_linux_ci.yml @@ -86,7 +86,6 @@ jobs: - name: Test CC (Linux) run: | - mv komodo-linux/komodo-linux.tar.gz . mkdir -p src tar xzvf komodo-linux.tar.gz ./zcutil/fetch-params.sh @@ -122,7 +121,6 @@ jobs: - name: Oracles Test (Linux) run: | - mv komodo-linux/komodo-linux.tar.gz . mkdir -p src tar xzvf komodo-linux.tar.gz ./zcutil/fetch-params.sh @@ -158,7 +156,6 @@ jobs: - name: BasicRPC Test (Linux) run: | - mv komodo-linux/komodo-linux.tar.gz . mkdir -p src tar xzvf komodo-linux.tar.gz ./zcutil/fetch-params.sh @@ -194,7 +191,6 @@ jobs: - name: Channels Test (Linux) run: | - mv komodo-linux/komodo-linux.tar.gz . mkdir -p src tar xzvf komodo-linux.tar.gz ./zcutil/fetch-params.sh @@ -230,7 +226,6 @@ jobs: - name: Heir Test (Linux) run: | - mv komodo-linux/komodo-linux.tar.gz . mkdir -p src tar xzvf komodo-linux.tar.gz ./zcutil/fetch-params.sh From a2b96c43b6f7d0e5573ce4601bc800e343c36d14 Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Wed, 8 Mar 2023 14:11:47 +0300 Subject: [PATCH 13/13] Pytests: update bootstrap domain --- qa/pytest_komodo/ci_set_dex.sh | 2 +- qa/pytest_komodo/ci_setup.sh | 2 +- qa/pytest_komodo/start_ci.bat | 2 +- qa/pytest_komodo/start_set_dex.bat | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/qa/pytest_komodo/ci_set_dex.sh b/qa/pytest_komodo/ci_set_dex.sh index 96aaaf395ca..d85d6ad7702 100755 --- a/qa/pytest_komodo/ci_set_dex.sh +++ b/qa/pytest_komodo/ci_set_dex.sh @@ -14,7 +14,7 @@ export TEST_WIF2="UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr" export TEST_PUBKEY2="02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9" export CHAIN_MODE="DEX2" export IS_BOOTSTRAP_NEEDED="True" -export BOOTSTRAP_URL="https://node.sirseven.me/fast_bootstrap.tar.gz" +export BOOTSTRAP_URL="https://node.dragonhound.info/fast_bootstrap.tar.gz" # starting the chains python3 chainstart.py diff --git a/qa/pytest_komodo/ci_setup.sh b/qa/pytest_komodo/ci_setup.sh index 791e28b561a..f282f80afc6 100755 --- a/qa/pytest_komodo/ci_setup.sh +++ b/qa/pytest_komodo/ci_setup.sh @@ -11,7 +11,7 @@ export TEST_WIF1="UwmmwgfXwZ673brawUarPzbtiqjsCPWnG311ZRAL4iUCZLBLYeDu" export TEST_PUBKEY1="0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149" export CHAIN_MODE="REGULAR" export IS_BOOTSTRAP_NEEDED="True" -export BOOTSTRAP_URL="https://node.sirseven.me/fast_bootstrap.tar.gz" +export BOOTSTRAP_URL="https://node.dragonhound.info/fast_bootstrap.tar.gz" # starting the chains python3 chainstart.py diff --git a/qa/pytest_komodo/start_ci.bat b/qa/pytest_komodo/start_ci.bat index 00b887898c6..8c1a01d43f7 100644 --- a/qa/pytest_komodo/start_ci.bat +++ b/qa/pytest_komodo/start_ci.bat @@ -8,7 +8,7 @@ set TEST_WIF1=UwmmwgfXwZ673brawUarPzbtiqjsCPWnG311ZRAL4iUCZLBLYeDu set TEST_PUBKEY1=0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149 set CHAIN_MODE=REGULAR set IS_BOOTSTRAP_NEEDED=True -set BOOTSTRAP_URL=https://node.sirseven.me/fast_bootstrap.tar.gz +set BOOTSTRAP_URL=https://node.dragonhound.info/fast_bootstrap.tar.gz python.exe chainstart.py diff --git a/qa/pytest_komodo/start_set_dex.bat b/qa/pytest_komodo/start_set_dex.bat index 774b5379e10..e45ee5c33c9 100644 --- a/qa/pytest_komodo/start_set_dex.bat +++ b/qa/pytest_komodo/start_set_dex.bat @@ -11,7 +11,7 @@ set TEST_WIF2=UqMLYDNVtYLPKZ2CcqeBU1FcYNHkknVZaMuQRqqZWXyPmSuJw3kr set TEST_PUBKEY2=02e9b141e1c251a942f77df10fa4de00f53f8ab2a6d5341bbaf842c95e674e92e9 set CHAIN_MODE=DEX2 set IS_BOOTSTRAP_NEEDED=True -set BOOTSTRAP_URL=https://node.sirseven.me/fast_bootstrap.tar.gz +set BOOTSTRAP_URL=https://node.dragonhound.info/fast_bootstrap.tar.gz python.exe chainstart.py