From 0d1fe52976fcb61ea4699cb912a3f423e1d96b38 Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Thu, 19 Dec 2019 23:09:44 +0700 Subject: [PATCH 1/9] Add parallel Linux tests, add basic komodod RPC tests --- .github/workflows/komodod_ci.yml | 232 +++++++++-- qa/rpc-tests/pytest_rpc/README.md | 40 ++ qa/rpc-tests/pytest_rpc/basic/pytest_util.py | 147 +++++++ qa/rpc-tests/pytest_rpc/basic/test_blocks.py | 388 ++++++++++++++++++ .../pytest_rpc/basic/test_control_address.py | 26 ++ .../pytest_rpc/basic/test_network_mining.py | 228 ++++++++++ .../pytest_rpc/basic/test_rawtransactions.py | 151 +++++++ .../pytest_rpc/basic/test_shielded.py | 227 ++++++++++ qa/rpc-tests/pytest_rpc/basic/test_utils.py | 110 +++++ qa/rpc-tests/pytest_rpc/basic/test_wallet.py | 366 +++++++++++++++++ .../pytest_rpc/cc_modules/test_channels.py | 229 +++++++++++ .../pytest_rpc/cc_modules/test_dice.py | 192 +++++++++ .../pytest_rpc/cc_modules/test_faucet.py | 106 +++++ .../pytest_rpc/cc_modules/test_heir.py | 152 +++++++ .../pytest_rpc/cc_modules/test_oracles.py | 287 +++++++++++++ .../pytest_rpc/cc_modules/test_rewards.py | 135 ++++++ .../pytest_rpc/cc_modules/test_token.py | 254 ++++++++++++ qa/rpc-tests/pytest_rpc/cc_modules/util.py | 88 ++++ qa/rpc-tests/pytest_rpc/chainconfig.json | 13 + qa/rpc-tests/pytest_rpc/chainstart.py | 140 +++++++ qa/rpc-tests/pytest_rpc/ci_setup.sh | 20 + qa/rpc-tests/pytest_rpc/conftest.py | 49 +++ qa/rpc-tests/pytest_rpc/helper.py | 70 ++++ qa/rpc-tests/pytest_rpc/nodesconfig.json | 23 ++ qa/rpc-tests/pytest_rpc/start_ci.bat | 15 + 25 files changed, 3664 insertions(+), 24 deletions(-) create mode 100644 qa/rpc-tests/pytest_rpc/README.md create mode 100644 qa/rpc-tests/pytest_rpc/basic/pytest_util.py create mode 100644 qa/rpc-tests/pytest_rpc/basic/test_blocks.py create mode 100644 qa/rpc-tests/pytest_rpc/basic/test_control_address.py create mode 100644 qa/rpc-tests/pytest_rpc/basic/test_network_mining.py create mode 100644 qa/rpc-tests/pytest_rpc/basic/test_rawtransactions.py create mode 100644 qa/rpc-tests/pytest_rpc/basic/test_shielded.py create mode 100644 qa/rpc-tests/pytest_rpc/basic/test_utils.py create mode 100644 qa/rpc-tests/pytest_rpc/basic/test_wallet.py create mode 100644 qa/rpc-tests/pytest_rpc/cc_modules/test_channels.py create mode 100644 qa/rpc-tests/pytest_rpc/cc_modules/test_dice.py create mode 100644 qa/rpc-tests/pytest_rpc/cc_modules/test_faucet.py create mode 100644 qa/rpc-tests/pytest_rpc/cc_modules/test_heir.py create mode 100644 qa/rpc-tests/pytest_rpc/cc_modules/test_oracles.py create mode 100644 qa/rpc-tests/pytest_rpc/cc_modules/test_rewards.py create mode 100644 qa/rpc-tests/pytest_rpc/cc_modules/test_token.py create mode 100644 qa/rpc-tests/pytest_rpc/cc_modules/util.py create mode 100644 qa/rpc-tests/pytest_rpc/chainconfig.json create mode 100644 qa/rpc-tests/pytest_rpc/chainstart.py create mode 100755 qa/rpc-tests/pytest_rpc/ci_setup.sh create mode 100644 qa/rpc-tests/pytest_rpc/conftest.py create mode 100644 qa/rpc-tests/pytest_rpc/helper.py create mode 100644 qa/rpc-tests/pytest_rpc/nodesconfig.json create mode 100644 qa/rpc-tests/pytest_rpc/start_ci.bat diff --git a/.github/workflows/komodod_ci.yml b/.github/workflows/komodod_ci.yml index a08865a3552..15e1c648d64 100644 --- a/.github/workflows/komodod_ci.yml +++ b/.github/workflows/komodod_ci.yml @@ -1,15 +1,11 @@ -name: CI test +name: Komodo CI on: [push, pull_request] jobs: - ci: - name: ${{ matrix.os }} CI - runs-on: ${{ matrix.os }} - - strategy: - matrix: - os: [macOS-latest, ubuntu-18.04] + linux-build: + name: Linux Build + runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 @@ -20,11 +16,17 @@ jobs: sudo apt-get remove php7.1-fpm php7.2-fpm php7.3-fpm 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 git python zlib1g-dev wget 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 libsodium-dev -y - sudo apt-get install python3.6 python3-pip python3-setuptools libgnutls28-dev - pip3 install setuptools wheel - pip3 install slick-bitcoinrpc pytest wget - # params we will need for tests execution + sudo apt-get update + 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 slick-bitcoinrpc pytest wget jsonschema ./zcutil/fetch-params.sh - name: Build (Linux) @@ -32,6 +34,13 @@ jobs: 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: + name: komodo-linux + path: ./komodo-linux.tar.gz # - name: Install deps (macOS) # if: runner.os == 'macOS' # run: | @@ -56,16 +65,192 @@ jobs: # CONFIGURE_FLAGS='CPPFLAGS=-DTESTMODE' ./zcutil/build-mac.sh -j4 # - name: Run CC tests # if: runner.os == 'Linux' || runner.os == 'macOS' - - name: Run CC tests - if: runner.os == 'Linux' + + + linux-test-maincc: + name: Test (Linux/mainCC) + runs-on: ubuntu-latest + needs: linux-build + + steps: + - uses: actions/checkout@v1 + + - name: Install deps (mainCC) + run: | + sudo apt-get update + 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 slick-bitcoinrpc pytest wget jsonschema + + - name: Download komodo-linux.tar.gz + uses: actions/download-artifact@v1 + with: + name: komodo-linux + + - name: Test (Linux) + run: | + mv komodo-linux/komodo-linux.tar.gz . + mkdir -p src + tar xzvf komodo-linux.tar.gz + ./zcutil/fetch-params.sh + cd qa/rpc-tests/pytest_rpc/ + ./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) + runs-on: ubuntu-latest + needs: linux-build + + steps: + - uses: actions/checkout@v1 + + - name: Install deps (OraclesCC) + run: | + sudo apt-get update + 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 slick-bitcoinrpc pytest wget jsonschema + + - name: Download komodo-linux.tar.gz + uses: actions/download-artifact@v1 + with: + name: komodo-linux + + - 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 + cd qa/rpc-tests/pytest_rpc/ + ./ci_setup.sh cc_modules/test_oracles.py + + linux-test-baserpc: + name: Test (Linux/BasicRPC) + runs-on: ubuntu-latest + needs: linux-build + + steps: + - uses: actions/checkout@v1 + + - name: Install deps (BasicRPC) + run: | + sudo apt-get update + 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 slick-bitcoinrpc pytest wget jsonschema + + - name: Download komodo-linux.tar.gz + uses: actions/download-artifact@v1 + with: + name: komodo-linux + + - 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 + cd qa/rpc-tests/pytest_rpc/ + ./ci_setup.sh basic + + linux-test-channels: + name: Test (Linux/ChannelsCC) + runs-on: ubuntu-latest + needs: linux-build + + steps: + - uses: actions/checkout@v1 + + - name: Install deps (ChannelsCC) + run: | + sudo apt-get update + 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 slick-bitcoinrpc pytest wget jsonschema + + - name: Download komodo-linux.tar.gz + uses: actions/download-artifact@v1 + with: + name: komodo-linux + + - name: Channels Test (Linux) run: | - cd qa/rpc-tests/cc_pytest - ./ci_setup.sh + mv komodo-linux/komodo-linux.tar.gz . + mkdir -p src + tar xzvf komodo-linux.tar.gz + ./zcutil/fetch-params.sh + cd qa/rpc-tests/pytest_rpc/ + ./ci_setup.sh cc_modules/test_channels.py + + linux-test-heir: + name: Test (Linux/HeirCC) + runs-on: ubuntu-latest + needs: linux-build - job-win-build: + steps: + - uses: actions/checkout@v1 + + - name: Install deps (HeirCC) + run: | + sudo apt-get update + 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 slick-bitcoinrpc pytest wget jsonschema + + - name: Download komodo-linux.tar.gz + uses: actions/download-artifact@v1 + with: + name: komodo-linux + + - 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 + cd qa/rpc-tests/pytest_rpc/ + ./ci_setup.sh cc_modules/test_heir.py + + windows-build: name: Win Build - runs-on: ubuntu-16.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 @@ -84,11 +269,10 @@ 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 - ./zcutil/build-win.sh -j 2 + CONFIGURE_FLAGS='CPPFLAGS=-DTESTMODE' ./zcutil/build-win.sh -j$(nproc) + zip --junk-paths komodod_win src/komodod.exe - name: Upload komodod.exe as artifact uses: actions/upload-artifact@v1 with: - name: komodod.exe - path: ./src/komodod.exe - - #TODO: windows tests + name: komodod_win + path: ./komodod_win.zip diff --git a/qa/rpc-tests/pytest_rpc/README.md b/qa/rpc-tests/pytest_rpc/README.md new file mode 100644 index 00000000000..67f2d606fab --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/README.md @@ -0,0 +1,40 @@ +Updated RPC unit-tests infrastructure for Antara smart-chain custom modules + +Using pytest as testing framework and slickrpc as rpc proxy. No more python2 support. + +To start just set test nodes RPC credentials in `nodesconfig.json`. +`chainconfig.json` contains daemon start cli params, change hardcoded parameters to use with your chain, default parmas are valid for test bootstrap `http://159.69.45.70/bootstrap.tar.gz` + +`is_fresh_chain=False` param allows to run tests on existing chains (it skips some tests which expecting first CC usage on chain) + +So yes - you can run these tests on existing chains, just RPC creds (and wallets with some balance) needed. + +# Dependencies +On Linux and MacOS: +```bash +pip3 install setuptools wheel slick-bitcoinrpc pytest wget jsonschema +``` +On Windows: +```cmd +pip3 install setuptools wheel python-bitcoinrpc pytest wget jsonschema +``` +slik-bitcoinrpc relies on libcurl and can have issues on Windows machines, thus we suggest to use different Proxy library. + +# Usage + +In `~/komodo/qa/rpc-tests/pytest_rpc` directory: + +`python3 -m pytest basic -s` - starts all basic tests +`python3 -m pytest cc_modules/test_dice.py -s` - starts specific test, dice in this case + +`-s` flag is optional, just displaying python prints which might be helpful in debugging + +`ci_test.sh cc_modules` script will start a all CCs full test suite from bootstrapped chain - best way to start the tests +You still can run specific test via script `ci_test.sh basic/test_utils.py` + +The `start_chains.py` script can spin needed amount of nodes and start the test chain. +You can find an example of this script usage in `ci_setup.sh`. Don't forget to change `test_config.json` accordingly to the chain params. + +On Windows machines use `start_ci.bat` instead of `ci_setup.sh` + +Also there is bootstrap downloading functionality in `start_chains.py` what should be quite useful for automated testing setups diff --git a/qa/rpc-tests/pytest_rpc/basic/pytest_util.py b/qa/rpc-tests/pytest_rpc/basic/pytest_util.py new file mode 100644 index 00000000000..da644c6c018 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/basic/pytest_util.py @@ -0,0 +1,147 @@ +import time +import jsonschema +import os +if os.name == 'posix': + from slickrpc import Proxy +else: + from bitcoinrpc.authproxy import AuthServiceProxy as 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 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(2) + 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'] + assert proxy.getinfo()['pubkey'] == env_params_dictionary.get('test_pubkey')[node] + assert proxy.getbalance() > 777 + + +def enable_mining(proxy): + cores = os.cpu_count() + if cores > 2: + threads_count = cores - 2 + else: + threads_count = 1 + proxy.setgenerate(True, threads_count) + + +def mine_and_waitconfirms(txid, proxy): # 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'] + break + except Exception 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 + if confirmations_amount < 2: + print("\ntx is not confirmed yet! Let's wait a little more") + time.sleep(5) + return True + else: + print("\ntx confirmed") + return True + + +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 + diff --git a/qa/rpc-tests/pytest_rpc/basic/test_blocks.py b/qa/rpc-tests/pytest_rpc/basic/test_blocks.py new file mode 100644 index 00000000000..75aba1b8992 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/basic/test_blocks.py @@ -0,0 +1,388 @@ +#!/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. + +import pytest +from pytest_util import validate_transaction +from pytest_util import validate_template +from decimal import * + + +@pytest.mark.usefixtures("proxy_connection") +class TestBlockchainMethods: + + def test_coinsupply(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getinfo() + height = res.get('blocks') + # fixed height + res = rpc.coinsupply(str(height)) + assert res.get('result') == 'success' + assert isinstance(res.get('height'), int) + # coinsupply without value should return max height + res = rpc.coinsupply() + assert res.get('result') == 'success' + assert isinstance(res.get('height'), int) + # invalid height + res = rpc.coinsupply("-1") + assert res.get('error') == "invalid height" + # invalid value + res = rpc.coinsupply("aaa") + assert res.get('error') == "couldnt calculate supply" + + def test_getbestblockhash(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getbestblockhash() + assert isinstance(res, str) + + def test_getblock(self, test_params): + test_values = { + 'block15': '15' + } + schema = { + 'type': 'object', + 'properties': { + 'last_notarized_height': {'type': 'integer'}, + 'hash': {'type': 'string'}, + 'confirmations': {'type': 'integer'}, + 'rawconfirmations': {'type': 'integer'}, + 'size': {'type': 'integer'}, + 'height': {'type': 'integer'}, + 'version': {'type': 'integer'}, + 'merkleroot': {'type': 'string'}, + 'segid': {'type': 'integer'}, + 'finalsaplingroot': {'type': 'string'}, + 'tx': {'type': 'array'}, + 'time': {'type': 'integer'}, + 'nonce': {'type': 'string'}, + 'solution': {'type': 'string'}, + 'bits': {'type': 'string'}, + 'difficulty': {'type': ['number', 'integer']}, + 'chainwork': {'type': 'string'}, + 'blocktype': {'type': 'string'}, + 'valuePools': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'id': {'type': 'string'}, + 'monitored': {'type': 'boolean'}, + 'chainValue': {'type': ['number', 'integer']}, + 'chainValueZat': {'type': ['number', 'integer']}, + 'valueDelta': {'type': ['number', 'integer']}, + 'valueDeltaZat': {'type': ['number', 'integer']} + } + } + }, + 'previousblockhash': {'type': 'string'}, + 'nextblockhash': {'type': 'string'} + }, + 'required': ['last_notarized_height', 'hash', 'confirmations', 'rawconfirmations', 'size', 'height', + 'version', 'merkleroot', 'segid', 'finalsaplingroot', 'tx', 'time', 'nonce', 'solution', + 'bits', 'difficulty', 'chainwork', 'anchor', 'blocktype', 'valuePools', + 'previousblockhash', 'nextblockhash'] + } + rpc = test_params.get('node1').get('rpc') + res = rpc.getblock(test_values['block15']) + validate_template(res, schema) + res = rpc.getblock(test_values['block15'], False) + assert isinstance(res, str) + + def test_getblockchaininfo(self, test_params): + schema = { + 'type': 'object', + 'required': ['chain', 'blocks', 'synced', 'headers', 'bestblockhash', 'upgrades', 'consensus', + 'difficulty', 'verificationprogress', 'chainwork', 'pruned', 'commitments'], + 'properties': { + 'chain': {'type': 'string'}, + 'blocks': {'type': 'integer'}, + 'synced': {'type': 'boolean'}, + 'headers': {'type': 'integer'}, + 'bestblockhash': {'type': 'string'}, + 'difficulty': {'type': ['integer', 'number']}, + 'verificationprogress': {'type': ['integer', 'number']}, + 'chainwork': {'type': 'string'}, + 'pruned': {'type': 'boolean'}, + 'commitments': {'type': ['integer', 'number']}, + 'valuePools': {'type': 'array', + 'items': {'type': 'object'}}, + 'upgrades': {'type': 'object'}, + 'consensus': {'type': 'object'} + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.getblockchaininfo() + validate_template(res, schema) + + def test_getblockcount(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getinfo() + height = res.get('blocks') + res = rpc.getblockcount() + assert res == height + + def test_getblockhash(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getinfo() + height = res.get('blocks') + res = rpc.getblockhash(height) + assert isinstance(res, str) + + # + # timestampindex -- required param + # + # def test_getblockhashes(self, test_params): + # test_values = { + # 'high': 101, + # 'low': 99, + # 'options': '{"noOrphans":false, "logicalTimes":true}' + # } + # rpc = test_params.get('node1').get('rpc') + # res = rpc.getblockhashes(test_values['high'], test_values['low'], test_values['options']) + + def test_getblockheader(self, test_params): + schema = { + 'type': 'object', + 'properties': { + 'last_notarized_height': {'type': 'integer'}, + 'hash': {'type': 'string'}, + 'confirmations': {'type': 'integer'}, + 'rawconfirmations': {'type': 'integer'}, + 'height': {'type': 'integer'}, + 'version': {'type': 'integer'}, + 'merkleroot': {'type': 'string'}, + 'segid': {'type': 'integer'}, + 'finalsaplingroot': {'type': 'string'}, + 'time': {'type': 'integer'}, + 'nonce': {'type': 'string'}, + 'solution': {'type': 'string'}, + 'bits': {'type': 'string'}, + 'difficulty': {'type': ['number', 'integer']}, + 'chainwork': {'type': 'string'}, + 'previousblockhash': {'type': 'string'}, + 'nextblockhash': {'type': 'string'} + }, + 'required': ['last_notarized_height', 'hash', 'confirmations', 'rawconfirmations', + 'height', 'version', 'merkleroot', 'segid', 'finalsaplingroot', 'time', + 'nonce', 'solution', 'bits', 'difficulty', 'chainwork', 'previousblockhash'] + } + rpc = test_params.get('node1').get('rpc') + res = rpc.getinfo() + block = res.get('blocks') + blockhash = rpc.getblockhash(block) + res1 = rpc.getblockheader(blockhash) + res2 = rpc.getblockheader(blockhash, True) + assert res1 == res2 + validate_template(res1, schema) + res = rpc.getblockheader(blockhash, False) + assert isinstance(res, str) + + def test_getchaintips(self, test_params): + schema = { + 'type': 'array', + 'items': { + 'type': 'object', + 'required': ['height', 'hash', 'branchlen', 'status'], + 'properties': { + 'height': {'type': 'integer'}, + 'hash': {'type': 'string'}, + 'branchlen': {'type': 'integer'}, + 'status': {'type': 'string'} + } + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.getchaintips() + validate_template(res, schema) + + def test_getchaintxstats(self, test_params): + schema = { + 'type': 'object', + 'properties': { + 'time': {'type': 'integer'}, + 'txcount': {'type': 'integer'}, + 'window_final_block_hash': {'type': 'string'}, + 'window_final_block_count': {'type': 'integer'}, + 'window_block_count': {'type': 'integer'}, + 'window_tx_count': {'type': 'integer'}, + 'window_interval': {'type': 'integer'}, + 'txrate': {'type': ['number', 'integer']} + }, + 'required': ['time', 'txcount', 'txrate', 'window_final_block_hash', 'window_interval', + 'window_block_count', 'window_tx_count'] + } + rpc = test_params.get('node1').get('rpc') + res = rpc.getchaintxstats() + validate_template(res, schema) + res = rpc.getinfo() + nblocks = (int(res.get('blocks')) - 100) + blockhash = rpc.getblockhash(res.get('blocks')) + res = rpc.getchaintxstats(nblocks) + validate_template(res, schema) + res = rpc.getchaintxstats(nblocks, blockhash) + validate_template(res, schema) + + def test_getdifficulty(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getdifficulty() + # python-bitcoinrpc Proxy can return value as decimal + assert isinstance(res, float) or isinstance(res, int) or isinstance(res, Decimal) + + # + # Only applies to -ac_staked Smart Chains + # + # def test_(self, test_params): + # test_values = {} + + def test_getmempoolinfo(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getmempoolinfo() + assert isinstance(res.get('size'), int) + assert isinstance(res.get('bytes'), int) + assert isinstance(res.get('usage'), int) + + # + # The method requires spentindex to be enabled. + # txid 68ee9d23ba51e40112be3957dd15bc5c8fa9a751a411db63ad0c8205bec5e8a1 + # + # def test_getspentinfo(self, test_params): + # pass + + def test_gettxout(self, test_params): + schema = { + 'type': 'object', + 'properties': { + 'bestblock': {'type': 'string'}, + 'confirmations': {'type': 'integer'}, + 'rawconfirmations': {'type': 'integer'}, + 'value': {'type': 'number'}, + 'scriptPubKey': { + 'type': 'object', + 'properties': { + 'asm': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'reqSigs': {'type': 'integer'}, + 'type': {'type': 'string'}, + 'addresses': { + 'type': 'array', + 'items': {'type': 'string'} + } + } + }, + 'version': {'type': 'integer'}, + 'coinbase': {'type': 'boolean'} + }, + 'required': ['bestblock', 'confirmations', 'rawconfirmations', + 'value', 'scriptPubKey', 'version', 'coinbase'] + } + rpc = test_params.get('node1').get('rpc') + res = rpc.listunspent() + txid = res[0].get('txid') + res = rpc.gettxout(txid, 0) + validate_template(res, schema) + res = rpc.gettxout(txid, -1) + assert not res # gettxout retuns None when vout does not exist + + def test_gettxoutproof(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.listunspent() + txid = res[0].get('txid') + res = rpc.gettxoutproof([txid]) + assert isinstance(res, str) + + def test_gettxoutsetinfo(self, test_params): + schema = { + 'type': 'object', + 'required': ['height', 'bestblock', 'transactions', 'txouts', 'bytes_serialized', + 'hash_serialized', 'total_amount'], + 'properties': { + 'height': {'type': 'integer'}, + 'bestblock': {'type': 'string'}, + 'transactions': {'type': 'integer'}, + 'txouts': {'type': 'integer'}, + 'bytes_serialized': {'type': 'integer'}, + 'hash_serialized': {'type': 'string'}, + 'total_amount': {'type': ['integer', 'number']} + } + } + rpc = test_params.get('node1').get('rpc') + 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') + assert res.get('notaries') # call should return list of notary nodes disregarding blocknum + + def test_minerids(self, test_params): + test_values = { + 'error': "couldnt extract minerids" + } + rpc = test_params.get('node1').get('rpc') + res = rpc.minerids('1') + assert res.get('error') == test_values['error'] or isinstance(res.get('mined'), list) + # likely to fail on bootstrap test chains + + def test_verifychain(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.verifychain() + assert res # rpc returns True if chain was verified + + def test_verifytxoutproof(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.listunspent() + txid = res[0].get('txid') + txproof = rpc.gettxoutproof([txid]) + res = rpc.verifytxoutproof(txproof) + assert res[0] == txid diff --git a/qa/rpc-tests/pytest_rpc/basic/test_control_address.py b/qa/rpc-tests/pytest_rpc/basic/test_control_address.py new file mode 100644 index 00000000000..df0ecaa8828 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/basic/test_control_address.py @@ -0,0 +1,26 @@ +#!/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. + +import pytest +import json + + +@pytest.mark.usefixtures("proxy_connection") +class TestControlAddress: + + def test_getinfo(self, test_params): + rpc1 = test_params.get('node1').get('rpc') + res = rpc1.getinfo() + assert res.get('blocks') + assert not res.get('errors') + rpc2 = test_params.get('node2').get('rpc') + res = rpc2.getinfo() + assert res.get('blocks') + assert not res.get('errors') + + def test_help(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.help() + assert "cclib method [evalcode] [JSON params]" in res diff --git a/qa/rpc-tests/pytest_rpc/basic/test_network_mining.py b/qa/rpc-tests/pytest_rpc/basic/test_network_mining.py new file mode 100644 index 00000000000..8a100f07165 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/basic/test_network_mining.py @@ -0,0 +1,228 @@ +#!/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. + +import pytest +import time +from decimal import * +from pytest_util import validate_template + + +@pytest.mark.usefixtures("proxy_connection") +class TestNetworkMining: + + def test_generate(self, test_params): # generate, getgenerate, setgenerate calls + rpc = test_params.get('node1').get('rpc') + res = rpc.setgenerate(False, -1) + assert not res + res = rpc.getgenerate() + assert not res.get('generate') + assert res.get('numthreads') == -1 + res = rpc.setgenerate(True, 1) + assert not res + res = rpc.getgenerate() + assert res.get('generate') + assert res.get('numthreads') == 1 + # rpc.generate(2) -- requires regtest mode + + def test_getmininginfo(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getinfo() + blocks = res.get('blocks') + rpc.setgenerate(True, 1) + res = rpc.getmininginfo() + assert res.get('blocks') == blocks + assert res.get('generate') + assert res.get('numthreads') == 1 + + def test_getblocksubsidy(self, test_params): + schema = { + 'type': 'object', + 'properties': { + 'miner': {'type': 'number'} + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.getblocksubsidy() + validate_template(res, schema) + res = rpc.getinfo() + block = res.get('blocks') + res = rpc.getblocksubsidy(block) + validate_template(res, schema) + + def test_getblocktemplate(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getblocktemplate() + validate_template(res) + + def test_getlocalsolps(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getlocalsolps() + # python-bitcoinrpc Proxy can return value as decimal + assert isinstance(res, float) or isinstance(res, int) or isinstance(res, Decimal) + + # getnetworkhashps call is deprecated + + def test_getnetworksolps(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getnetworksolps() + assert isinstance(res, float) or isinstance(res, int) + + def test_prioritisetransaction(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.prioritisetransaction("68ee9d23ba51e40112be3957dd15bc5c8fa9a751a411db63ad0c8205bec5e8a1", 0.0, 10000) + assert res # returns True on success + + def test_submitblock(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getinfo() + height = res.get('blocks') + block = rpc.getblock(str(height), False) + res = rpc.submitblock(block) + assert res == 'duplicate' + + def test_getnetworkinfo(self, test_params): + schema = { + 'type': 'object', + 'properties': { + 'version': {'type': 'integer'}, + 'subversion': {'type': 'string'}, + 'protocolversion': {'type': 'integer'}, + 'localservices': {'type': 'string'}, + 'timeoffset': {'type': 'integer'}, + 'connections': {'type': 'integer'}, + 'networks': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'name': {'type': 'string'}, + 'limited': {'type': 'boolean'}, + 'reachable': {'type': 'boolean'}, + 'proxy': {'type': 'string'}, + 'proxy_randomize_credentials': {'type': 'boolean'}, + } + } + }, + 'relayfee': {'type': 'number'}, + 'localadresses': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'address': {'type': 'string'}, + 'port': {'type': 'integer'}, + 'score': {'type': 'integer'}, + }, + 'required': ['address', 'port', 'score'] + } + }, + 'warnings': {'type': 'string'} + }, + 'required': ['version', 'subversion', 'protocolversion', 'localservices', 'timeoffset', 'connections', + 'networks', 'relayfee', 'localaddresses', 'warnings'] + } + rpc = test_params.get('node1').get('rpc') + res = rpc.getnetworkinfo() + validate_template(res, schema) + + def test_getconnectioncount(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getconnectioncount() + assert isinstance(res, int) + + def test_getpeerinfo(self, test_params): + schema = { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'id': {'type': 'integer'}, + 'addr': {'type': 'string'}, + 'addrlocal': {'type': 'string'}, + 'services': {'type': 'string'}, + 'lastsend': {'type': 'integer'}, + 'lastrecv': {'type': 'integer'}, + 'bytessent': {'type': 'integer'}, + 'bytesrecv': {'type': 'integer'}, + 'conntime': {'type': 'integer'}, + 'timeoffset': {'type': 'integer'}, + 'pingtime': {'type': ['number', 'integer']}, + 'pingwait': {'type': ['number', 'integer']}, + 'version': {'type': 'integer'}, + 'subver': {'type': 'string'}, + 'inbound': {'type': 'boolean'}, + 'startingheight': {'type': 'integer'}, + 'banscore': {'type': ['number', 'integer']}, + 'synced_headers': {'type': 'integer'}, + 'synced_blocks': {'type': 'integer'}, + 'inflight': {'type': 'array'}, + 'whitelisted': {'type': 'boolean'}, + 'number': {'type': 'integer'} + } + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.getpeerinfo() + validate_template(res, schema) + + def test_getnettotals(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getnettotals() + assert isinstance(res.get('timemillis'), int) + + def test_ping(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.ping() + assert not res # ping call has empty response + + def test_getdeprecationinfo(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getdeprecationinfo() + assert isinstance(res.get('version'), int) + + def test_addnode(self, test_params): + rpc = test_params.get('node2').get('rpc') + cnode_ip = test_params.get('node1').get('rpc_ip') + connect_node = (cnode_ip + ':' + str(test_params.get('node1').get('net_port'))) + res = rpc.addnode(connect_node, 'remove') + assert not res + res = rpc.addnode(connect_node, 'onetry') + assert not res + res = rpc.addnode(connect_node, 'add') + assert not res + rpc.ping() + + def test_disconnectnode(self, test_params): + rpc = test_params.get('node2').get('rpc') + cnode_ip = test_params.get('node1').get('rpc_ip') + disconnect_node = (cnode_ip + ':' + str(test_params.get('node1').get('net_port'))) + rpc.addnode(disconnect_node, 'remove') # remove node from addnode list to prevent reconnection + res = rpc.disconnectnode(disconnect_node) # has empty response + assert not res + time.sleep(15) # time to stop node connection + res = rpc.getpeerinfo() + for peer in res: + assert peer.get('addr') != disconnect_node + rpc.addnode(disconnect_node, 'add') + time.sleep(10) # wait for 2nd to reconnect after test + + def test_ban(self, test_params): # setban, listbanned, clearbanned calls + rpc = test_params.get('node1').get('rpc') + ban_list = ['144.144.140.0/255.255.255.0', '144.144.140.12/255.255.255.255', '192.168.0.0/255.255.0.0'] + res = rpc.clearbanned() + assert not res + res = rpc.setban(ban_list[0], 'add', 64800) + assert not res + res = rpc.setban(ban_list[1], 'add', 64800) + assert not res + res = rpc.setban(ban_list[2], 'add', 64800) + assert not res + res = rpc.listbanned() + for peer in res: + node = peer.get('address') + assert node in ban_list + rpc.clearbanned() + res = rpc.listbanned() + assert not res diff --git a/qa/rpc-tests/pytest_rpc/basic/test_rawtransactions.py b/qa/rpc-tests/pytest_rpc/basic/test_rawtransactions.py new file mode 100644 index 00000000000..9847eda8bc3 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/basic/test_rawtransactions.py @@ -0,0 +1,151 @@ +#!/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. + +import pytest +from decimal import * +from pytest_util import validate_template, mine_and_waitconfirms + + +@pytest.mark.usefixtures("proxy_connection") +class TestRawTransactions: + + def test_rawtransactions(self, test_params): # create, fund, sign, send calls + fund_schema = { + 'type': 'object', + 'properties': { + 'hex': {'type': 'string'}, + 'fee': {'type': ['integer', 'number']}, + 'changepos': {'type': ['integer', 'number']} + } + } + sign_schema = { + 'type': 'object', + 'properties': { + 'hex': {'type': 'string'}, + 'complete': {'type': 'boolean'} + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.listunspent() + txid = res[0].get('txid') + vout = res[0].get('vout') + base_amount = res[0].get('amount') + if isinstance(base_amount, Decimal): + amount = float(base_amount) * 0.9 + print(amount) + else: + amount = base_amount * 0.9 + address = rpc.getnewaddress() + ins = [{'txid': txid, 'vout': vout}] + outs = {address: amount} + + rawtx = rpc.createrawtransaction(ins, outs) + assert isinstance(rawtx, str) + + fundtx = rpc.fundrawtransaction(rawtx) + validate_template(fundtx, fund_schema) + + signtx = rpc.signrawtransaction(fundtx.get('hex')) + validate_template(signtx, sign_schema) + assert signtx['complete'] + + sendtx = rpc.sendrawtransaction(signtx.get('hex')) + assert isinstance(sendtx, str) + assert mine_and_waitconfirms(sendtx, rpc) + + def test_getrawtransaction(self, test_params): # decode, get methods + txschema = { + 'type': 'object', + 'properties': { + 'hex': {'type': 'string'}, + 'txid': {'type': 'string'}, + 'overwintered': {'type': 'boolean'}, + 'version': {'type': 'integer'}, + 'versiongroupid': {'type': 'string'}, + 'locktime': {'type': 'integer'}, + 'expiryheight': {'type': 'integer'}, + 'vin': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'coinbase': {'type': 'string'}, + 'txid': {'type': 'string'}, + 'vout': {'type': 'integer'}, + 'address': {'type': 'string'}, + 'scriptSig': { + 'type': 'object', + 'properties': { + 'asm': {'type': 'string'}, + 'hex': {'type': 'string'} + } + }, + 'value': {'type': ['integer', 'number']}, + 'valueSat': {'type': 'integer'}, + 'sequence': {'type': 'integer'} + } + } + }, + 'vout': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'value': {'type': ['integer', 'number']}, + 'valueSat': {'type': 'integer'}, + 'interest': {'type': ['integer', 'number']}, + 'n': {'type': 'integer'}, + 'scriptPubKey': { + 'type': 'object', + 'properties': { + 'asm': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'reqSigs': {'type': 'integer'}, + 'type': {'type': 'string'}, + 'addresses': {'type': 'array', 'items': {'type': 'string'}} + } + } + } + } + }, + 'vjoinsplit': {'type': 'array'}, + 'valueBalance': {'type': 'number'}, + 'vShieldedSpend': {'type': 'array'}, + 'vShieldedOutput': {'type': 'array'}, + 'blockhash': {'type': 'string'}, + 'height': {'type': 'integer'}, + 'confirmations': {'type': 'integer'}, + 'rawconfirmations': {'type': 'integer'}, + 'time': {'type': 'integer'}, + 'blocktime': {'type': 'integer'} + } + } + scriptschema = { + 'type': 'object', + 'properties': { + 'asm': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'type': {'type': 'string'}, + 'reqSigs': {'type': 'integer'}, + 'address': {'type': 'string'}, + 'p2sh': {'type': 'string'}, + 'addresses': {'type': 'array', + 'items': {'type': 'string'}} + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.listunspent() + txid = res[0].get('txid') + rawhex = rpc.getrawtransaction(txid) + assert isinstance(rawhex, str) + res = rpc.getrawtransaction(txid, 1) + validate_template(res, txschema) + + scripthex = res.get('vout')[0].get('scriptPubKey').get('hex') + res = rpc.decodescript(scripthex) + validate_template(res, scriptschema) + + res = rpc.decoderawtransaction(rawhex) + validate_template(res, txschema) diff --git a/qa/rpc-tests/pytest_rpc/basic/test_shielded.py b/qa/rpc-tests/pytest_rpc/basic/test_shielded.py new file mode 100644 index 00000000000..6b86542d7c6 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/basic/test_shielded.py @@ -0,0 +1,227 @@ +#!/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. + +import pytest +import time +from decimal import * +from pytest_util import validate_template, check_synced, mine_and_waitconfirms + + +@pytest.mark.usefixtures("proxy_connection") +class TestZcalls: + + def test_z_getnewaddress(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.z_getnewaddress() + assert isinstance(res, str) + # test sendmany, operationstatus, operationresult and listreceivedbyaddress calls + + def test_z_send(self, test_params): + schema = { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'id': {'type': 'string'}, + 'status': {'type': 'string'}, + 'creation_time': {'type': 'integer'}, + 'execution_secs': {'type': ['number', 'integer']}, + 'method': {'type': 'string'}, + 'error': { + 'type': 'object', + 'properties': { + 'code': {'type': 'integer'}, + 'message': {'type': 'string'} + } + }, + 'result': { + 'type': 'object', + 'properties': {'txid': {'type': 'string'}} + }, + 'params': { + 'type': 'object', + 'properties': { + 'fromaddress': {'type': 'string'}, + 'minconf': {'type': 'integer'}, + 'fee': {'type': ['number', 'integer']}, + 'amounts': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'address': {'type': 'string'}, + 'amount': {'type': ['integer', 'number']} + } + } + } + } + } + } + } + } + schema_list = { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'txid': {'type': 'string'}, + 'memo': {'type': 'string'}, + 'amount': {'type': ['number', 'integer']}, + 'change': {'type': 'boolean'}, + 'outindex': {'type': 'integer'}, + 'confirmations': {'type': 'integer'}, + 'rawconfirmations': {'type': 'integer'}, + 'jsoutindex': {'type': 'integer'}, + 'jsindex': {'type': 'integer'} + } + } + } + rpc1 = test_params.get('node1').get('rpc') + rpc2 = test_params.get('node2').get('rpc') + transparent1 = rpc1.getnewaddress() + shielded1 = rpc1.z_getnewaddress() + transparent2 = rpc2.getnewaddress() + shielded2 = rpc2.z_getnewaddress() + amount1 = rpc1.getbalance() / 100 + amount2 = amount1 / 10 + try: + import slickrpc + authproxy = 0 + except ImportError: + authproxy = 1 + if authproxy: # type correction when using python-bitcoinrpc Proxy + amount1 = float(amount1) + amount2 = float(amount2) + # python float() is double precision floating point number, + # where z_sendmany expects regural float (8 digits) value + # "{0:.8f}".format(value)) returns number string with 8 digit precision and float() corrects the type + t_send1 = [{'address': transparent1, 'amount': float("{0:.8f}".format(amount2))}] + t_send2 = [{'address': transparent2, 'amount': float("{0:.8f}".format(amount2 * 0.4))}] + z_send1 = [{'address': shielded1, 'amount': float("{0:.8f}".format(amount2 * 0.95))}] + z_send2 = [{'address': shielded2, 'amount': float("{0:.8f}".format(amount2 * 0.4))}] + cases = [(transparent1, t_send1), (transparent1, z_send1), (shielded1, t_send2), (shielded1, z_send2)] + # sendmany cannot use coinbase tx vouts + txid = rpc1.sendtoaddress(transparent1, amount1) + mine_and_waitconfirms(txid, rpc1) + for case in cases: + assert check_synced(rpc1) # to perform z_sendmany nodes should be synced + opid = rpc1.z_sendmany(case[0], case[1]) + assert isinstance(opid, str) + attempts = 0 + while True: + res = rpc1.z_getoperationstatus([opid]) + validate_template(res, schema) + status = res[0].get('status') + if status == 'success': + print('Operation successfull\nWaiting confirmations\n') + res = rpc1.z_getoperationresult([opid]) # also clears op from memory + validate_template(res, schema) + txid = res[0].get('result').get('txid') + time.sleep(30) + tries = 0 + while True: + try: + res = rpc1.getrawtransaction(txid, 1) + confirms = res['confirmations'] + print('TX confirmed \nConfirmations: ', confirms) + break + except Exception as e: + print("\ntx is in mempool still probably, let's wait a little bit more\nError: ", e) + time.sleep(5) + tries += 1 + if tries < 100: + pass + else: + print("\nwaited too long - probably tx stuck by some reason") + return False + break + else: + attempts += 1 + print('Waiting operation result\n') + time.sleep(10) + if attempts >= 100: + print('operation takes too long, aborting\n') + return False + res = rpc1.z_listreceivedbyaddress(shielded1) + validate_template(res, schema_list) + + def test_z_getbalance(self, test_params): + rpc = test_params.get('node1').get('rpc') + zaddr = rpc.z_getnewaddress() + res = rpc.z_getbalance(zaddr, 1) + assert isinstance(res, float) or isinstance(res, int) or isinstance(res, Decimal) + + def test_z_gettotalbalance(self, test_params): + schema = { + 'type': 'object', + 'properties': { + 'transparent': {'type': ['string']}, + 'interest': {'type': ['string']}, + 'private': {'type': ['string']}, + 'total': {'type': ['string']}, + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.z_gettotalbalance(1) + validate_template(res, schema) + + def test_z_export_viewing_key(self, test_params): + rpc = test_params.get('node1').get('rpc') + zaddr = rpc.z_getnewaddress() + res = rpc.z_exportkey(zaddr) + assert isinstance(res, str) + res = rpc.z_exportviewingkey(zaddr) + assert isinstance(res, str) + + def test_z_import_viewing_key(self, test_params): + rpc1 = test_params.get('node1').get('rpc') + rpc2 = test_params.get('node2').get('rpc') + zaddr = rpc2.z_getnewaddress() + zkey = rpc2.z_exportkey(zaddr) + zvkey = rpc2.z_exportviewingkey(zaddr) + # res = rpc1.z_importviewingkey(zvkey) # https://github.com/zcash/zcash/issues/3060 + # assert not res + res = rpc1.z_importkey(zkey) + assert not res + + def test_z_listaddresses(self, test_params): + schema = { + 'type': 'array', + 'items': { + 'type': 'string' + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.z_listaddresses() + validate_template(res, schema) + + def test_z_listopertaionsids(self, test_params): + schema = { + 'type': 'array', + 'items': { + 'type': 'string' + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.z_listoperationids() + validate_template(res, schema) + res = rpc.z_listoperationids('success') + validate_template(res, schema) + + def test_z_validateaddress(self, test_params): + schema = { + 'type': 'object', + 'properties': { + 'isvalid': {'type': 'boolean'}, + 'address': {'type': 'string'}, + 'payingkey': {'type': 'string'}, + 'transmissionkey': {'type': 'string'}, + 'ismine': {'type': 'boolean'} + } + } + rpc = test_params.get('node1').get('rpc') + zaddr = rpc.z_getnewaddress() + res = rpc.z_validateaddress(zaddr) + validate_template(res, schema) diff --git a/qa/rpc-tests/pytest_rpc/basic/test_utils.py b/qa/rpc-tests/pytest_rpc/basic/test_utils.py new file mode 100644 index 00000000000..da95a296773 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/basic/test_utils.py @@ -0,0 +1,110 @@ +#!/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. + +import pytest +from pytest_util import validate_template + + +@pytest.mark.usefixtures("proxy_connection") +class TestUtil: + + def test_createmultisig(self, test_params): + schema = { + 'type': 'object', + 'properties': { + 'address': {'type': 'string'}, + 'redeemScript': {'type': 'string'}, + } + } + rpc = test_params.get('node1').get('rpc') + keys = [test_params.get('node1').get('pubkey'), test_params.get('node2').get('pubkey')] + res = rpc.createmultisig(2, keys) + validate_template(res, schema) + + def test_decodeccopret(self, test_params): + rpc = test_params.get('node1').get('rpc') + schema = { + 'type': 'object', + 'properties': { + 'result': {'type': 'string'}, + 'OpRets': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'eval_code': {'type': 'string'}, + 'function': {'type': 'string'} + } + } + } + } + } + rawhex = rpc.oraclescreate('TEST', 'Orale creation tx for test purpose', 'L') + res = rpc.decoderawtransaction(rawhex.get('hex')) + vouts = res.get('vout') + ccopret = '' + for n in vouts: + if n.get('scriptPubKey').get('type') == 'nulldata': + ccopret = n.get('scriptPubKey').get('hex') + break + res = rpc.decodeccopret(ccopret) + assert res.get('result') == 'success' + validate_template(res, schema) + + def test_estimatefee(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.estimatefee(6) + assert isinstance(res, int) or isinstance(res, float) + + def test_estimatepriority(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.estimatepriority(6) + assert isinstance(res, int) or isinstance(res, float) + + def test_invalidate_reconsider_block(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getinfo() + block = res.get('blocks') + blockhash = rpc.getblockhash(block) + res = rpc.invalidateblock(blockhash) + assert not res # none response on success + res = rpc.reconsiderblock(blockhash) + assert not res # none response on success + + def test_txnotarizedconfirmed(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.listunspent() + txid = res[0].get('txid') + res = rpc.txnotarizedconfirmed(txid) + assert isinstance(res.get('result'), bool) + + def test_validateaddress(self, test_params): + schema = { + 'type': 'object', + 'properties': { + 'isvalid': {'type': 'boolean'}, + 'ismine': {'type': 'boolean'}, + 'isscript': {'type': 'boolean'}, + 'iscompressed': {'type': 'boolean'}, + 'account': {'type': 'string'}, + 'pubkey': {'type': 'string'}, + 'address': {'type': 'string'}, + 'scriptPubKey': {'type': 'string'}, + 'segid': {'type': 'integer'} + } + } + rpc = test_params.get('node1').get('rpc') + addr = test_params.get('node1').get('address') + res = rpc.validateaddress(addr) + validate_template(res, schema) + assert addr == res.get('address') + + def test_verifymessage(self, test_params): + rpc = test_params.get('node1').get('rpc') + addr = test_params.get('node1').get('address') + sign = rpc.signmessage(addr, 'test test') + assert isinstance(sign, str) + res = rpc.verifymessage(addr, sign, "test test") + assert isinstance(res, bool) diff --git a/qa/rpc-tests/pytest_rpc/basic/test_wallet.py b/qa/rpc-tests/pytest_rpc/basic/test_wallet.py new file mode 100644 index 00000000000..eb12e0c69d1 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/basic/test_wallet.py @@ -0,0 +1,366 @@ +#!/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. + +import pytest +import os +import time +from decimal import * +from pytest_util import validate_template + + +@pytest.mark.usefixtures("proxy_connection") +class TestWalletRPC: + + def test_addmultisigadress(self, test_params): + pass + + def test_getbalance(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getbalance() + # python-bitcoinrpc Proxy can return value as decimal + assert isinstance(res, float) or isinstance(res, int) or isinstance(res, Decimal) + + def test_getnewaddress(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getnewaddress() + assert isinstance(res, str) + + def test_dumpprivkey(self, test_params): + rpc = test_params.get('node1').get('rpc') + addr = rpc.getnewaddress() + res = rpc.dumpprivkey(addr) + assert isinstance(res, str) + + def test_getrawchangeaddress(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getrawchangeaddress() + assert isinstance(res, str) + + def test_getreceivedbyaddress(self, test_params): + rpc = test_params.get('node1').get('rpc') + addr = rpc.getnewaddress() + res = rpc.getreceivedbyaddress(addr) + # python-bitcoinrpc Proxy can return value as decimal + assert isinstance(res, float) or isinstance(res, int) or isinstance(res, Decimal) + + def test_gettransaction(self, test_params): + schema = { + 'type': 'object', + 'properties': { + 'amount': {'type': ['integer', 'number']}, + 'rawconfirmations': {'type': 'integer'}, + 'confirmations': {'type': 'integer'}, + 'blockindex': {'type': 'integer'}, + 'blocktime': {'type': 'integer'}, + 'walletconflicts': {'type': 'array'}, + 'time': {'type': 'integer'}, + 'timereceived': {'type': 'integer'}, + 'txid': {'type': 'string'}, + 'blockhash': {'type': 'string'}, + 'hex': {'type': 'string'}, + 'vjoinsplit': { + 'type': 'array', + 'items': {'type': 'object'} + }, + 'details': { + 'type': 'array', + 'properties': { + 'account': {'type': 'string'}, + 'address': {'type': 'string'}, + 'category': {'type': 'string'}, + 'amount': {'type': ['number', 'integer']}, + 'vout': {'type': 'integer'}, + 'size': {'type': 'integer'}, + } + } + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.listunspent() + txid = res[0].get('txid') + res = rpc.gettransaction(txid) + validate_template(res, schema) + + def test_getunconfirmedbalance(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.getunconfirmedbalance() + # python-bitcoinrpc Proxy can return value as decimal + assert isinstance(res, float) or isinstance(res, int) or isinstance(res, Decimal) + + def test_getwalletinfo(self, test_params): + schema = { + 'type': 'object', + 'properties': { + 'walletversion': {'type': 'integer'}, + 'balance': {'type': ['number', 'integer']}, + 'unconfirmed_balance': {'type': ['number', 'integer']}, + 'immature_balance': {'type': ['number', 'integer']}, + 'txount': {'type': 'integer'}, + 'keypoololdest': {'type': 'integer'}, + 'keypoolsize': {'type': 'integer'}, + 'paytxfee': {'type': ['number', 'integer']}, + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.getwalletinfo() + validate_template(res, schema) + + def test_importaddress(self, test_params): + rpc1 = test_params.get('node1').get('rpc') + rpc2 = test_params.get('node2').get('rpc') + addr = rpc2.getnewaddress() + res = rpc1.importaddress(addr) + assert not res # empty response on success + + def test_importprivkey(self, test_params): + rpc = test_params.get('node1').get('rpc') + addr = rpc.getnewaddress() + key = rpc.dumpprivkey(addr) + res = rpc.importprivkey(key) + assert isinstance(res, str) + + def test_keypoolrefill(self, test_params): + rpc = test_params.get('node1').get('rpc') + res = rpc.keypoolrefill(100) + assert not res # empty response on success + + def test_listaddressgroupings(self, test_params): + schema = { + 'type': 'array', + 'items': { + 'type': 'array', + 'items': { + 'type': 'array', + 'items': {'type': ['string', 'integer', 'number']} + } + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.listaddressgroupings() + validate_template(res, schema) + + def test_list_lockunspent(self, test_params): + schema = { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'txid': {'type': 'string'}, + 'vout': {'type': 'integer'} + } + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.listunspent() + txid = res[0].get('txid') + lock = [{"txid": txid, "vout": 0}] + res = rpc.lockunspent(False, lock) + assert res # returns True on success + res = rpc.listlockunspent() + validate_template(res, schema) + res = rpc.lockunspent(True, lock) + assert res # returns True on success + + def test_listreceivedbyaddress(self, test_params): + schema = { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'involvesWatchonly': {'type': 'boolean'}, + 'address': {'type': 'string'}, + 'account': {'type': 'string'}, + 'amount': {'type': ['integer', 'number']}, + 'rawconfirmations': {'type': 'integer'}, + 'confirmations': {'type': 'integer'}, + 'txids': { + 'type': 'array', + 'items': {'type': 'string'} + } + } + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.listreceivedbyaddress() + validate_template(res, schema) + + def test_listsinceblock(self, test_params): + schema = { + 'type': 'object', + 'properties': { + 'lastblock': {'type': 'string'}, + 'transactions': { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'account': {'type': 'string'}, + 'address': {'type': 'string'}, + 'category': {'type': 'string'}, + 'blockhash': {'type': 'string'}, + 'txid': {'type': 'string'}, + 'vjoinsplit': {'type': 'array'}, + 'walletconflicts': {'type': 'array'}, + 'amount': {'type': ['integer', 'number']}, + 'vout': {'type': 'integer'}, + 'rawconfirmations': {'type': 'integer'}, + 'confirmations': {'type': 'integer'}, + 'blockindex': {'type': 'integer'}, + 'blocktime': {'type': 'integer'}, + 'expiryheight': {'type': 'integer'}, + 'time': {'type': 'integer'}, + 'timereceived': {'type': 'integer'}, + 'size': {'type': 'integer'}, + 'to': {'type': 'string'}, + 'comment': {'type': 'string'} + } + } + } + } + } + rpc = test_params.get('node1').get('rpc') + blockhash = rpc.getbestblockhash() + res = rpc.listsinceblock(blockhash, 1) + validate_template(res, schema) + + def test_listtransactions(self, test_params): + schema = { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'account': {'type': 'string'}, + 'address': {'type': 'string'}, + 'category': {'type': 'string'}, + 'blockhash': {'type': 'string'}, + 'txid': {'type': 'string'}, + 'vjoinsplit': {'type': 'array'}, + 'walletconflicts': {'type': 'array'}, + 'amount': {'type': ['integer', 'number']}, + 'vout': {'type': 'integer'}, + 'rawconfirmations': {'type': 'integer'}, + 'confirmations': {'type': 'integer'}, + 'blockindex': {'type': 'integer'}, + 'fee': {'type': ['integer', 'number']}, + 'time': {'type': 'integer'}, + 'timereceived': {'type': 'integer'}, + 'size': {'type': 'integer'}, + 'comment': {'type': 'string'}, + 'otheraccount': {'type': 'string'} + } + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.listtransactions() + validate_template(res, schema) + + def test_listunspent(self, test_params): + schema = { + 'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'txid': {'type': 'string'}, + 'address': {'type': 'string'}, + 'scriptPubKey': {'type': 'string'}, + 'generated': {'type': 'boolean'}, + 'spendable': {'type': 'boolean'}, + 'vout': {'type': 'integer'}, + 'confirmations': {'type': 'integer'}, + 'rawconfirmations': {'type': 'integer'}, + 'amount': {'type': ['integer', 'number']}, + 'interest': {'type': ['integer', 'number']} + } + } + } + rpc = test_params.get('node1').get('rpc') + res = rpc.listunspent() + validate_template(res, schema) + + def test_resendwallettransactions(self, test_params): + schema = { + 'type': 'array', + 'itmes': {'type': 'string'} + } + rpc = test_params.get('node1').get('rpc') + res = rpc.resendwallettransactions() + validate_template(res, schema) + + def test_settxfee(self, test_params): + txfee = 0.00001 + rpc = test_params.get('node1').get('rpc') + res = rpc.settxfee(txfee) + assert res # returns True on success + + def test_signmessage(self, test_params): + message = "my test message" + rpc = test_params.get('node1').get('rpc') + addr = rpc.getnewaddress() + sign = rpc.signmessage(addr, message) + assert isinstance(sign, str) + res = rpc.verifymessage(addr, sign, message) + assert res # returns True on success + + def test_sendtoaddress(self, test_params): + rpc = test_params.get('node1').get('rpc') + addr = rpc.getnewaddress() + amount = rpc.getbalance() / 1000 + txid = rpc.sendtoaddress(addr, amount) + assert isinstance(txid, str) + # wait tx to be confirmed + attempts = 0 + while True: + print('waiting tx to be confirmed\n') + confs = rpc.getrawtransaction(txid, 1).get('confirmations') + if confs: + if confs > 1: + print("TX confirmed\n") + break + if attempts > 100: + return False + else: + attempts += 1 + time.sleep(10) + + def test_sendmany(self, test_params): + rpc1 = test_params.get('node1').get('rpc') + rpc2 = test_params.get('node2').get('rpc') + address1 = rpc1.getnewaddress() + address2 = rpc2.getnewaddress() + # python float() is double precision floating point number, + # where sendmany expects regural float (8 digits) value + # "{0:.8f}".format(value)) returns number string with 8 digit precision and float() corrects the type + amount = float("{0:.8f}".format(rpc1.getbalance() / 1000)) # float("{0:.8f}".format(amount2)) + send = {address1: amount, address2: amount} + txid = rpc1.sendmany("", send) + assert isinstance(txid, str) + # wait tx to be confirmed + attempts = 0 + while True: + print('waiting tx to be confirmed\n') + confs = rpc1.getrawtransaction(txid, 1).get('confirmations') + if confs: + if confs > 1: + print("TX confirmed\n") + break + if attempts > 100: + return False + else: + attempts += 1 + time.sleep(10) + + def test_setupkey(self, test_params): + schema = { + 'type': 'object', + 'properties': { + 'address': {'type': 'string'}, + 'pubkey': {'type': 'string'}, + 'ismine': {'type': 'boolean'} + } + } + rpc = test_params.get('node1').get('rpc') + pubkey = test_params.get('node1').get('pubkey') + res = rpc.setpubkey(pubkey) + validate_template(res, schema) diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/test_channels.py b/qa/rpc-tests/pytest_rpc/cc_modules/test_channels.py new file mode 100644 index 00000000000..c67ba6587ac --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/cc_modules/test_channels.py @@ -0,0 +1,229 @@ +#!/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. + +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 == True + + # 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 == True + + # 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 = True +# assert secret_not_revealed == True +# +# # 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" diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/test_dice.py b/qa/rpc-tests/pytest_rpc/cc_modules/test_dice.py new file mode 100644 index 00000000000..d031bee33ea --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/cc_modules/test_dice.py @@ -0,0 +1,192 @@ +#!/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. + +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']))) diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/test_faucet.py b/qa/rpc-tests/pytest_rpc/cc_modules/test_faucet.py new file mode 100644 index 00000000000..137c9848ff3 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/cc_modules/test_faucet.py @@ -0,0 +1,106 @@ +#!/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. + +import pytest +import json + +from util import assert_success, assert_error, check_if_mined, send_and_mine, rpc_connect + + +@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' + + # 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 diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/test_heir.py b/qa/rpc-tests/pytest_rpc/cc_modules/test_heir.py new file mode 100644 index 00000000000..dd384704bb4 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/cc_modules/test_heir.py @@ -0,0 +1,152 @@ +#!/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. + +import pytest +import time +import json + +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_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 11 seconds to be sure that needed time passed for heir claiming + time.sleep(11) + 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" diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/test_oracles.py b/qa/rpc-tests/pytest_rpc/cc_modules/test_oracles.py new file mode 100644 index 00000000000..b4003c72062 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/cc_modules/test_oracles.py @@ -0,0 +1,287 @@ +#!/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. + +import pytest +import os + +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']) + + wait_some_blocks(rpc, 1) + + for f in valid_formats: + # trying to register with negative datafee + result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "-100") + assert_error(result) + + # trying to register with zero datafee + result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "0") + assert_error(result) + + # trying to register with datafee less than txfee + result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "500") + assert_error(result) + + # 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"]) + assert fund_txid, "got txid" + + wait_some_blocks(rpc, 1) + + for f in valid_formats: + # trying to register valid (funded) + result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "10000") + print(f) + assert_success(result) + 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']) diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/test_rewards.py b/qa/rpc-tests/pytest_rpc/cc_modules/test_rewards.py new file mode 100644 index 00000000000..64a9be11ca7 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/cc_modules/test_rewards.py @@ -0,0 +1,135 @@ +#!/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. + +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) diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/test_token.py b/qa/rpc-tests/pytest_rpc/cc_modules/test_token.py new file mode 100644 index 00000000000..a1642cc306c --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/cc_modules/test_token.py @@ -0,0 +1,254 @@ +#!/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. + +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 diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/util.py b/qa/rpc-tests/pytest_rpc/cc_modules/util.py new file mode 100644 index 00000000000..28b2ebd3382 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/cc_modules/util.py @@ -0,0 +1,88 @@ +import pytest +import time +import sys +import os +from random import choice +from string import ascii_uppercase +if os.name == 'posix': + from slickrpc import Proxy +else: + from bitcoinrpc.authproxy import AuthServiceProxy as Proxy + + +def assert_success(result): + assert result['result'] == 'success' + + +def assert_error(result): + assert result['result'] == 'error' + + +def check_if_mined(rpc_connection, txid): + attempts = 0 + while True: + try: + confirmations_amount = rpc_connection.getrawtransaction(txid, 1)["confirmations"] + break + except Exception as e: + print(e, file=sys.stderr) + print("tx is in mempool still probably, let's wait a little bit more", file=sys.stderr) + time.sleep(5) + attempts = attempts + 1 + if attempts < 100: + pass + else: + print("waited too long - probably tx stuck by some reason") + if confirmations_amount < 2: + print("tx is not confirmed yet! Let's wait a little more", file=sys.stderr) + time.sleep(5) + + +def send_and_mine(tx_hex, rpc_connection): + txid = rpc_connection.sendrawtransaction(tx_hex) + assert txid, 'got txid' + # we need the tx above to be confirmed in the next block + check_if_mined(rpc_connection, txid) + return txid + + +def rpc_connect(rpc_user, rpc_password, ip, port): + try: + rpc_connection = Proxy("http://%s:%s@%s:%d" % (rpc_user, rpc_password, ip, port)) + except Exception: + raise Exception("Connection error! Probably no daemon on selected port.") + return rpc_connection + + +def wait_some_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: + break + + +def generate_random_string(length): + random_string = ''.join(choice(ascii_uppercase) for i in range(length)) + return random_string + + +def komodo_teardown(*proxy_instances): + for instance in proxy_instances: + if type(instance) is list: + for iteratable in instance: + try: + isinstance(iteratable, Proxy) + iteratable.stop() + except Exception as e: + raise TypeError("Not a Proxy object, error: " + str(e)) + else: + try: + isinstance(instance, Proxy) + instance.stop() + except Exception as e: + raise TypeError("Not a Proxy object, error: " + str(e)) diff --git a/qa/rpc-tests/pytest_rpc/chainconfig.json b/qa/rpc-tests/pytest_rpc/chainconfig.json new file mode 100644 index 00000000000..92b2d7205c8 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/chainconfig.json @@ -0,0 +1,13 @@ +{ + "TONYCI": { + "coin": "TONYCI", + "rpc_user": "test", + "rpcpassword": "test", + "rpcallowip": "0.0.0.0/0", + "rpcport": "7000", + "rpcbind": "0.0.0.0", + "ac_reward": "100000000000", + "ac_supply": "10000000000", + "ac_cc": "2" + } +} \ No newline at end of file diff --git a/qa/rpc-tests/pytest_rpc/chainstart.py b/qa/rpc-tests/pytest_rpc/chainstart.py new file mode 100644 index 00000000000..5bc638ffe20 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/chainstart.py @@ -0,0 +1,140 @@ +import os +import json +import time +import subprocess +import wget +import tarfile +from basic.pytest_util import create_proxy, validate_proxy, enable_mining + + +def load_env_config(): + tp = {} # test env parameters + if os.name == 'posix': + envconfig = './envconfig.json' + else: + envconfig = 'envconfig.json' + if os.environ['CHAIN']: + tp.update({'clients_to_start': int(os.environ['CLIENTS'])}) + tp.update({'is_bootstrap_needed': os.environ['IS_BOOTSTRAP_NEEDED']}) + tp.update({'bootstrap_url': os.environ['BOOTSTRAP_URL']}) + tp.update({'chain_start_mode': os.environ['CHAIN_MODE']}) + tp.update({'ac_name': os.environ['CHAIN']}) + test_wif_list = [] # preset empty params lists + test_addr_list = [] + test_pubkey_list = [] + for i in range(tp.get('clients_to_start')): + test_wif_list.append(os.environ["TEST_WIF" + str(i)]) + test_addr_list.append(os.environ["TEST_ADDY" + str(i)]) + test_pubkey_list.append(os.environ["TEST_PUBKEY" + str(i)]) + tp.update({'test_wif': test_wif_list}) + tp.update({'test_address': test_addr_list}) + tp.update({'test_pubkey': test_pubkey_list}) + elif os.path.isfile(envconfig) and not os.environ['CHAIN']: + with open(envconfig, 'r') as f: + tp = json.load(f) + else: + raise EnvironmentError("\nNo test env configuration provided") + return tp + + +def load_ac_params(asset, chain_mode='default'): + if os.name == 'posix': + chainconfig = './chainconfig.json' + binary_path = '../../../src/komodod' + else: + chainconfig = (os.getcwd() + '\\chainconfig.json') + binary_path = (os.getcwd() + '\\..\\..\\..\\src\\komodod.exe') + if os.path.isfile(chainconfig): + with open(chainconfig, 'r') as f: + jsonparams = json.load(f) + ac = jsonparams.get(asset) # asset chain parameters + ac.update({'binary_path': binary_path}) + if chain_mode == 'REGTEST': + ac.update({'daemon_params': ['-daemon', '-whitelist=127.0.0.1', '-regtest']}) + else: + ac.update({'daemon_params': ['-daemon', '-whitelist=127.0.0.1']}) + else: + raise EnvironmentError("\nNo asset chains configuration provided") + return ac + + +# TODO: add coins file compatibility with create_configs func +def create_configs(asset, node=0): + if os.name == 'posix': + confpath = ('./node_' + str(node) + '/' + asset + '.conf') + else: + confpath = (os.getcwd() + '\\node_' + str(node) + '\\' + asset + '.conf') + if not os.path.isfile(confpath): + os.mkdir('node_' + str(node)) + open(confpath, 'a').close() + with open(confpath, 'a') as conf: + conf.write("rpcuser=test\n") + conf.write("rpcpassword=test\n") + conf.write('rpcport=' + str(7000 + node) + '\n') + conf.write("rpcbind=0.0.0.0\n") + conf.write("rpcallowip=0.0.0.0/0\n") + + +def main(): + env_params = load_env_config() + clients_to_start = env_params.get('clients_to_start') + aschain = env_params.get('ac_name') + for node in range(clients_to_start): # prepare config folders + create_configs(aschain, node) + if env_params.get('is_bootstrap_needed'): # bootstrap chains + if not os.path.isfile('bootstrap.tar.gz'): + wget.download(env_params.get('bootstrap_url'), "bootstrap.tar.gz") + tf = tarfile.open("bootstrap.tar.gz") + for i in range(clients_to_start): + tf.extractall("node_" + str(i)) + mode = env_params.get('chain_start_mode') + ac_params = load_ac_params(aschain, mode) + for i in range(clients_to_start): # start daemons + if os.name == 'posix': + confpath = (os.getcwd() + '/node_' + str(i) + '/' + aschain + '.conf') + datapath = (os.getcwd() + '/node_' + str(i)) + else: + confpath = (os.getcwd() + '\\node_' + str(i) + '\\' + aschain + '.conf') + datapath = (os.getcwd() + '\\node_' + str(i)) + cl_args = [ac_params.get('binary_path'), + '-ac_name=' + aschain, + '-conf=' + confpath, + '-rpcport=' + str(7000 + i), + '-port=' + str(6000 + i), + '-datadir=' + datapath, + '-pubkey=' + env_params.get('test_pubkey')[i], + ] + if i > 0: + cl_args.append('-addnode=127.0.0.1:6000') + if ac_params.get('ac_reward'): + cl_args.append('-ac_reward=' + ac_params.get('ac_reward')) + else: + cl_args.append('-ac_reward=100000000000') + if ac_params.get('ac_supply'): + cl_args.append('-ac_supply=' + ac_params.get('ac_supply')) + else: + cl_args.append('-ac_supply=10000000000') + if ac_params.get('ac_cc'): + cl_args.append('-ac_cc=' + ac_params.get('ac_cc')) + else: + cl_args.append('-ac_cc=2') + cl_args.extend(ac_params.get('daemon_params')) + if os.name == "posix": + subprocess.call(cl_args) + else: + subprocess.Popen(cl_args, shell=False, stderr=subprocess.PIPE, stdout=subprocess.PIPE) + time.sleep(5) + for i in range(clients_to_start): + node_params = { + 'rpc_user': 'test', + 'rpc_password': 'test', + 'rpc_ip': '127.0.0.1', + 'rpc_port': 7000 + i + } + rpc_p = create_proxy(node_params) + validate_proxy(env_params, rpc_p, i) + enable_mining(rpc_p) + + +if __name__ == '__main__': + main() diff --git a/qa/rpc-tests/pytest_rpc/ci_setup.sh b/qa/rpc-tests/pytest_rpc/ci_setup.sh new file mode 100755 index 00000000000..cdd39412770 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/ci_setup.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# chains start script params +export CLIENTS=2 +export CHAIN="TONYCI" +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="http://159.69.45.70/bootstrap.tar.gz" + +# starting the chains +python3 chainstart.py + +# starting the tests +python3 -m pytest $@ -s -vv diff --git a/qa/rpc-tests/pytest_rpc/conftest.py b/qa/rpc-tests/pytest_rpc/conftest.py new file mode 100644 index 00000000000..e8b4b9263a2 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/conftest.py @@ -0,0 +1,49 @@ +import pytest +import json +import os +import time +# Using different proxy to bypass libcurl issues on Windows +if os.name == 'posix': + from slickrpc import Proxy +else: + from bitcoinrpc.authproxy import AuthServiceProxy as Proxy + + +@pytest.fixture(scope='session') +def proxy_connection(): + proxy_connected = [] + + 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=120) + proxy_connected.append(proxy) + except Exception as e: + raise Exception("Connection error! Probably no daemon on selected port. Error: ", e) + return proxy + + yield _proxy_connection + + for each in proxy_connected: + print("\nStopping created proxies...") + time.sleep(10) # time wait for tests to finish correctly before stopping daemon + try: # while using AuthServiceProxy, stop method results in connection aborted error + each.stop() + except ConnectionAbortedError as e: + print(e) + + +@pytest.fixture(scope='session') +def test_params(proxy_connection): + with open('nodesconfig.json', 'r') as f: + params_dict = json.load(f) + node1_params = params_dict['node1'] + node2_params = params_dict['node2'] + rpc1 = proxy_connection(node1_params) + rpc2 = proxy_connection(node2_params) + test_params = {'node1': node1_params, 'node2': node2_params} + test_params['node1'].update({'rpc': rpc1}) + test_params['node2'].update({'rpc': rpc2}) + return test_params diff --git a/qa/rpc-tests/pytest_rpc/helper.py b/qa/rpc-tests/pytest_rpc/helper.py new file mode 100644 index 00000000000..72bb17ade19 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/helper.py @@ -0,0 +1,70 @@ +import os +import time +from decimal import * +from basic.pytest_util import validate_template +if os.name == 'posix': + from slickrpc import Proxy +else: + from bitcoinrpc.authproxy import AuthServiceProxy as Proxy + + +def main(): + node_params_dictionary1 = { + "rpc_user": "test", + "rpc_password": "test", + "rpc_ip": "127.0.0.1", + "rpc_port": 7000 + } + rpc1 = Proxy("http://%s:%s@%s:%d" % (node_params_dictionary1.get('rpc_user'), + node_params_dictionary1.get('rpc_password'), + node_params_dictionary1.get('rpc_ip'), + node_params_dictionary1.get('rpc_port'))) + + node_params_dictionary2 = { + "rpc_user": "test", + "rpc_password": "test", + "rpc_ip": "127.0.0.1", + "rpc_port": 7001 + } + rpc2 = Proxy("http://%s:%s@%s:%d" % (node_params_dictionary2.get('rpc_user'), + node_params_dictionary2.get('rpc_password'), + node_params_dictionary2.get('rpc_ip'), + node_params_dictionary2.get('rpc_port'))) + + #rpc1.setgenerate(True, 1) + #rpc2.setgenerate(True, 1) + #transparent1 = rpc1.getnewaddress() + #print(transparent1) + #shielded1 = rpc1.z_getnewaddress() + #print(shielded1) + #transparent2 = rpc2.getnewaddress() + #print(transparent2) + #shielded2 = rpc2.z_getnewaddress() + #print(shielded2) + #res = rpc1.z_gettotalbalance() + #print(res) + #res = rpc1.z_getbalance(shielded1) + #print(res) + #res = rpc1.getinfo().get("synced") + #print(res) + #res = rpc2.getinfo().get("synced") + #print(res) + #res = rpc1.listunspent() + #print(res) + #res = rpc2.z_listunspent() + #print(res) + #amount = rpc1.getbalance() / 1000 + #print(amount) + #t_send = [{'address': 'zs10h8kdr3r98rkekfhn3za7mu4vjgpe4h96mwqk3ww2pt33n7jjzktrwhuksxqqd2ztg2awj9y8cp', + # 'amount': '55,11'}] + ##z_send = [{'address': shielded2, 'amount': amount}] + #opid = rpc1.z_sendmany('RBvTN4GT9nVhH7BbJV2MYkfFLSwQvTA17H', t_send) + ##print(opid) + #res = rpc1.z_getoperationstatus([opid]) + #print(res) + rpc1.stop() + rpc2.stop() + + +if __name__ == '__main__': + main() diff --git a/qa/rpc-tests/pytest_rpc/nodesconfig.json b/qa/rpc-tests/pytest_rpc/nodesconfig.json new file mode 100644 index 00000000000..10ba3e45e46 --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/nodesconfig.json @@ -0,0 +1,23 @@ +{ + "node1" : { + "rpc_user" : "test", + "rpc_password" : "test", + "rpc_ip" : "127.0.0.1", + "rpc_port": 7000, + "net_port": 6000, + "pubkey" : "02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7", + "address": "RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd", + "txid": "64b5e5151f027095803e4a8d98d66e8d2777f54321b232ece84d364a046606fb" + }, + "node2" : { + "rpc_user" : "test", + "rpc_password" : "test", + "rpc_ip" : "127.0.0.1", + "rpc_port": 7001, + "net_port": 6001, + "pubkey" : "0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149", + "address": "RHoTHYiHD8TU4k9rbY4Aoj3ztxUARMJikH", + "txid": "79d6b61ab663579d3682747b82f1118c1678e1759ccbd6749b67905572681bfb" + }, + "is_fresh_chain": true +} \ No newline at end of file diff --git a/qa/rpc-tests/pytest_rpc/start_ci.bat b/qa/rpc-tests/pytest_rpc/start_ci.bat new file mode 100644 index 00000000000..9aac73072aa --- /dev/null +++ b/qa/rpc-tests/pytest_rpc/start_ci.bat @@ -0,0 +1,15 @@ +set CLIENTS=2 +set CHAIN=TONYCI +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=http://159.69.45.70/bootstrap.tar.gz + +python.exe chainstart.py + +python.exe -m pytest %* -s -vv From 224dc8ebaa18642afa9a0d59b7e529d9bb63abb3 Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Fri, 20 Dec 2019 05:28:17 +0700 Subject: [PATCH 2/9] precision fix for sendtoaddress method --- qa/rpc-tests/pytest_rpc/basic/test_wallet.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/qa/rpc-tests/pytest_rpc/basic/test_wallet.py b/qa/rpc-tests/pytest_rpc/basic/test_wallet.py index eb12e0c69d1..32af032c8c8 100644 --- a/qa/rpc-tests/pytest_rpc/basic/test_wallet.py +++ b/qa/rpc-tests/pytest_rpc/basic/test_wallet.py @@ -306,7 +306,10 @@ def test_signmessage(self, test_params): def test_sendtoaddress(self, test_params): rpc = test_params.get('node1').get('rpc') addr = rpc.getnewaddress() - amount = rpc.getbalance() / 1000 + # python float() is double precision floating point number, + # where sendmany expects regural float (8 digits) value + # "{0:.8f}".format(value)) returns number string with 8 digit precision and float() corrects the type + amount = float("{0:.8f}".format(rpc.getbalance() / 1000)) txid = rpc.sendtoaddress(addr, amount) assert isinstance(txid, str) # wait tx to be confirmed @@ -329,9 +332,7 @@ def test_sendmany(self, test_params): rpc2 = test_params.get('node2').get('rpc') address1 = rpc1.getnewaddress() address2 = rpc2.getnewaddress() - # python float() is double precision floating point number, - # where sendmany expects regural float (8 digits) value - # "{0:.8f}".format(value)) returns number string with 8 digit precision and float() corrects the type + # clarification in test_sendtoaddress above amount = float("{0:.8f}".format(rpc1.getbalance() / 1000)) # float("{0:.8f}".format(amount2)) send = {address1: amount, address2: amount} txid = rpc1.sendmany("", send) From 4dd3e0d04549b87e4c09f71c64f1a4993aea5bca Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Fri, 20 Dec 2019 19:48:36 +0700 Subject: [PATCH 3/9] restructure tests folder --- .../pytest_rpc => pytest_komodo}/README.md | 0 .../basic/pytest_util.py | 0 .../basic/test_blocks.py | 0 .../basic/test_control_address.py | 0 .../basic/test_network_mining.py | 0 .../basic/test_rawtransactions.py | 0 .../basic/test_shielded.py | 0 .../basic/test_utils.py | 0 .../basic/test_wallet.py | 0 .../cc_modules/test_channels.py | 0 .../cc_modules/test_dice.py | 0 .../cc_modules/test_faucet.py | 0 .../cc_modules/test_heir.py | 0 .../cc_modules/test_oracles.py | 0 .../cc_modules/test_rewards.py | 0 .../cc_modules/test_token.py | 0 .../cc_modules/util.py | 0 .../chainconfig.json | 0 .../chainstart.py | 4 +- .../pytest_rpc => pytest_komodo}/ci_setup.sh | 0 .../pytest_rpc => pytest_komodo}/conftest.py | 0 .../pytest_rpc => pytest_komodo}/helper.py | 0 .../nodesconfig.json | 0 .../pytest_rpc => pytest_komodo}/start_ci.bat | 0 qa/rpc-tests/cc_pytest/README.md | 32 -- qa/rpc-tests/cc_pytest/ci_setup.sh | 20 -- qa/rpc-tests/cc_pytest/start_chains.py | 147 --------- qa/rpc-tests/cc_pytest/test_channels.py | 232 -------------- qa/rpc-tests/cc_pytest/test_config.json | 17 -- qa/rpc-tests/cc_pytest/test_dice.py | 194 ------------ qa/rpc-tests/cc_pytest/test_faucet.py | 110 ------- qa/rpc-tests/cc_pytest/test_heir.py | 153 ---------- qa/rpc-tests/cc_pytest/test_oracles.py | 289 ------------------ qa/rpc-tests/cc_pytest/test_rewards.py | 135 -------- qa/rpc-tests/cc_pytest/test_token.py | 256 ---------------- qa/rpc-tests/cc_pytest/util.py | 67 ---- 36 files changed, 2 insertions(+), 1654 deletions(-) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/README.md (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/basic/pytest_util.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/basic/test_blocks.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/basic/test_control_address.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/basic/test_network_mining.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/basic/test_rawtransactions.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/basic/test_shielded.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/basic/test_utils.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/basic/test_wallet.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/cc_modules/test_channels.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/cc_modules/test_dice.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/cc_modules/test_faucet.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/cc_modules/test_heir.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/cc_modules/test_oracles.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/cc_modules/test_rewards.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/cc_modules/test_token.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/cc_modules/util.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/chainconfig.json (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/chainstart.py (97%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/ci_setup.sh (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/conftest.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/helper.py (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/nodesconfig.json (100%) rename qa/{rpc-tests/pytest_rpc => pytest_komodo}/start_ci.bat (100%) delete mode 100644 qa/rpc-tests/cc_pytest/README.md delete mode 100755 qa/rpc-tests/cc_pytest/ci_setup.sh delete mode 100644 qa/rpc-tests/cc_pytest/start_chains.py delete mode 100644 qa/rpc-tests/cc_pytest/test_channels.py delete mode 100644 qa/rpc-tests/cc_pytest/test_config.json delete mode 100644 qa/rpc-tests/cc_pytest/test_dice.py delete mode 100644 qa/rpc-tests/cc_pytest/test_faucet.py delete mode 100644 qa/rpc-tests/cc_pytest/test_heir.py delete mode 100644 qa/rpc-tests/cc_pytest/test_oracles.py delete mode 100644 qa/rpc-tests/cc_pytest/test_rewards.py delete mode 100644 qa/rpc-tests/cc_pytest/test_token.py delete mode 100644 qa/rpc-tests/cc_pytest/util.py diff --git a/qa/rpc-tests/pytest_rpc/README.md b/qa/pytest_komodo/README.md similarity index 100% rename from qa/rpc-tests/pytest_rpc/README.md rename to qa/pytest_komodo/README.md diff --git a/qa/rpc-tests/pytest_rpc/basic/pytest_util.py b/qa/pytest_komodo/basic/pytest_util.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/basic/pytest_util.py rename to qa/pytest_komodo/basic/pytest_util.py diff --git a/qa/rpc-tests/pytest_rpc/basic/test_blocks.py b/qa/pytest_komodo/basic/test_blocks.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/basic/test_blocks.py rename to qa/pytest_komodo/basic/test_blocks.py diff --git a/qa/rpc-tests/pytest_rpc/basic/test_control_address.py b/qa/pytest_komodo/basic/test_control_address.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/basic/test_control_address.py rename to qa/pytest_komodo/basic/test_control_address.py diff --git a/qa/rpc-tests/pytest_rpc/basic/test_network_mining.py b/qa/pytest_komodo/basic/test_network_mining.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/basic/test_network_mining.py rename to qa/pytest_komodo/basic/test_network_mining.py diff --git a/qa/rpc-tests/pytest_rpc/basic/test_rawtransactions.py b/qa/pytest_komodo/basic/test_rawtransactions.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/basic/test_rawtransactions.py rename to qa/pytest_komodo/basic/test_rawtransactions.py diff --git a/qa/rpc-tests/pytest_rpc/basic/test_shielded.py b/qa/pytest_komodo/basic/test_shielded.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/basic/test_shielded.py rename to qa/pytest_komodo/basic/test_shielded.py diff --git a/qa/rpc-tests/pytest_rpc/basic/test_utils.py b/qa/pytest_komodo/basic/test_utils.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/basic/test_utils.py rename to qa/pytest_komodo/basic/test_utils.py diff --git a/qa/rpc-tests/pytest_rpc/basic/test_wallet.py b/qa/pytest_komodo/basic/test_wallet.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/basic/test_wallet.py rename to qa/pytest_komodo/basic/test_wallet.py diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/test_channels.py b/qa/pytest_komodo/cc_modules/test_channels.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/cc_modules/test_channels.py rename to qa/pytest_komodo/cc_modules/test_channels.py diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/test_dice.py b/qa/pytest_komodo/cc_modules/test_dice.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/cc_modules/test_dice.py rename to qa/pytest_komodo/cc_modules/test_dice.py diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/test_faucet.py b/qa/pytest_komodo/cc_modules/test_faucet.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/cc_modules/test_faucet.py rename to qa/pytest_komodo/cc_modules/test_faucet.py diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/test_heir.py b/qa/pytest_komodo/cc_modules/test_heir.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/cc_modules/test_heir.py rename to qa/pytest_komodo/cc_modules/test_heir.py diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/test_oracles.py b/qa/pytest_komodo/cc_modules/test_oracles.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/cc_modules/test_oracles.py rename to qa/pytest_komodo/cc_modules/test_oracles.py diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/test_rewards.py b/qa/pytest_komodo/cc_modules/test_rewards.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/cc_modules/test_rewards.py rename to qa/pytest_komodo/cc_modules/test_rewards.py diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/test_token.py b/qa/pytest_komodo/cc_modules/test_token.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/cc_modules/test_token.py rename to qa/pytest_komodo/cc_modules/test_token.py diff --git a/qa/rpc-tests/pytest_rpc/cc_modules/util.py b/qa/pytest_komodo/cc_modules/util.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/cc_modules/util.py rename to qa/pytest_komodo/cc_modules/util.py diff --git a/qa/rpc-tests/pytest_rpc/chainconfig.json b/qa/pytest_komodo/chainconfig.json similarity index 100% rename from qa/rpc-tests/pytest_rpc/chainconfig.json rename to qa/pytest_komodo/chainconfig.json diff --git a/qa/rpc-tests/pytest_rpc/chainstart.py b/qa/pytest_komodo/chainstart.py similarity index 97% rename from qa/rpc-tests/pytest_rpc/chainstart.py rename to qa/pytest_komodo/chainstart.py index 5bc638ffe20..bdeadcff1c4 100644 --- a/qa/rpc-tests/pytest_rpc/chainstart.py +++ b/qa/pytest_komodo/chainstart.py @@ -40,10 +40,10 @@ def load_env_config(): def load_ac_params(asset, chain_mode='default'): if os.name == 'posix': chainconfig = './chainconfig.json' - binary_path = '../../../src/komodod' + binary_path = '../../src/komodod' else: chainconfig = (os.getcwd() + '\\chainconfig.json') - binary_path = (os.getcwd() + '\\..\\..\\..\\src\\komodod.exe') + binary_path = (os.getcwd() + '\\..\\..\\src\\komodod.exe') if os.path.isfile(chainconfig): with open(chainconfig, 'r') as f: jsonparams = json.load(f) diff --git a/qa/rpc-tests/pytest_rpc/ci_setup.sh b/qa/pytest_komodo/ci_setup.sh similarity index 100% rename from qa/rpc-tests/pytest_rpc/ci_setup.sh rename to qa/pytest_komodo/ci_setup.sh diff --git a/qa/rpc-tests/pytest_rpc/conftest.py b/qa/pytest_komodo/conftest.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/conftest.py rename to qa/pytest_komodo/conftest.py diff --git a/qa/rpc-tests/pytest_rpc/helper.py b/qa/pytest_komodo/helper.py similarity index 100% rename from qa/rpc-tests/pytest_rpc/helper.py rename to qa/pytest_komodo/helper.py diff --git a/qa/rpc-tests/pytest_rpc/nodesconfig.json b/qa/pytest_komodo/nodesconfig.json similarity index 100% rename from qa/rpc-tests/pytest_rpc/nodesconfig.json rename to qa/pytest_komodo/nodesconfig.json diff --git a/qa/rpc-tests/pytest_rpc/start_ci.bat b/qa/pytest_komodo/start_ci.bat similarity index 100% rename from qa/rpc-tests/pytest_rpc/start_ci.bat rename to qa/pytest_komodo/start_ci.bat diff --git a/qa/rpc-tests/cc_pytest/README.md b/qa/rpc-tests/cc_pytest/README.md deleted file mode 100644 index 30b2a50f232..00000000000 --- a/qa/rpc-tests/cc_pytest/README.md +++ /dev/null @@ -1,32 +0,0 @@ -Updated RPC unit-tests infrastructure for Antara smart-chain custom modules - -Using pytest as testing framework and slickrpc as rpc proxy. No more python2 support. - -To start just set test nodes RPC credentials in `test_config.json`. -I thought such config usage might be useful as in some manual testing plays as well as in some CI configuration tests integration. - -`is_fresh_chain=False` param allows to run tests on existing chains (it skips some tests which expecting first CC usage on chain) - -So yes - you can run these tests on existing chains, just RPC creds (and wallets with some balance) needed. - -# Dependencies - -`pip3 install setuptools wheel slick-bitcoinrpc pytest wget` - -# Usage - -In `~/komodo/qa/rpc-tests/cc_pytest` directory: - -`python3 -m pytest -s` - starts all tests suite -`python3 -m pytest test_dice.py -s` - starts specific test, dice in this case - -`-s` flag is optional, just displaying python prints which might be helpful in debugging - -`ci_test.sh` script will start a all CCs full test suite from bootstrapped chain - best way to start the tests - -The `start_chains.py` script can spin needed amount of nodes and start the test chain. -You can find an example of this script usage in `ci_setup.sh`. Don't forget to change `test_config.json` accordingly to the chain params. - -Also there is bootstrap downloading functionality in `start_chains.py` what should be quite useful for automated testing setups - -Happy testing! <3 \ No newline at end of file diff --git a/qa/rpc-tests/cc_pytest/ci_setup.sh b/qa/rpc-tests/cc_pytest/ci_setup.sh deleted file mode 100755 index 9df2efdfaf0..00000000000 --- a/qa/rpc-tests/cc_pytest/ci_setup.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -# chains start script params -export CLIENTS=2 -export CHAIN="TONYCI" -export TEST_ADDY="RPWhA4f4ZTZxNi5K36bcwsWdVjSVDSjUnd" -export TEST_WIF="UpcQympViQpLmv1WzMwszKPrmKUa28zsv8pdLCMgNMXDFBBBKxCN" -export TEST_PUBKEY="02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7" -export TEST_ADDY2="RHoTHYiHD8TU4k9rbY4Aoj3ztxUARMJikH" -export TEST_WIF2="UwmmwgfXwZ673brawUarPzbtiqjsCPWnG311ZRAL4iUCZLBLYeDu" -export TEST_PUBKEY2="0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149" -export CHAIN_MODE="REGULAR" -export IS_BOOTSTRAP_NEEDED="True" -export BOOTSTRAP_URL="http://159.69.45.70/bootstrap.tar.gz" - -# starting the chains -python3 start_chains.py - -# starting the tests -python3 -m pytest -s diff --git a/qa/rpc-tests/cc_pytest/start_chains.py b/qa/rpc-tests/cc_pytest/start_chains.py deleted file mode 100644 index 143d29474bb..00000000000 --- a/qa/rpc-tests/cc_pytest/start_chains.py +++ /dev/null @@ -1,147 +0,0 @@ -import os -import time -import sys -import subprocess -import wget -import tarfile -from slickrpc import Proxy - - -clients_to_start = int(os.environ['CLIENTS']) -ac_name = os.environ['CHAIN'] -# node1 params -test_address = os.environ['TEST_ADDY'] -test_wif = os.environ['TEST_WIF'] -test_pubkey = os.environ['TEST_PUBKEY'] -# node2 params -test_address2 = os.environ['TEST_ADDY2'] -test_wif2 = os.environ['TEST_WIF2'] -test_pubkey2 = os.environ['TEST_PUBKEY2'] -# expecting REGTEST or REGULAR there -chain_start_mode = os.environ['CHAIN_MODE'] -# expecting True or False string there -is_boostrap_needed = os.environ['IS_BOOTSTRAP_NEEDED'] -bootstrap_url = os.environ['BOOTSTRAP_URL'] - -# pre-creating separate folders and configs -for i in range(clients_to_start): - os.mkdir("node_" + str(i)) - open("node_" + str(i) + "/" + ac_name + ".conf", 'a').close() - with open("node_" + str(i) + "/" + ac_name + ".conf", 'a') as conf: - conf.write("rpcuser=test" + '\n') - conf.write("rpcpassword=test" + '\n') - conf.write("rpcport=" + str(7000 + i) + '\n') - conf.write("rpcbind=0.0.0.0\n") - conf.write("rpcallowip=0.0.0.0/0\n") - - -if is_boostrap_needed == "True": - wget.download(bootstrap_url, "bootstrap.tar.gz") - tf = tarfile.open("bootstrap.tar.gz") - for i in range(clients_to_start): - tf.extractall("node_" + str(i)) - -# start numnodes daemons, changing folder name and port -for i in range(clients_to_start): - # all nodes should search for first "mother" node - if i == 0: - start_args = ['../../../src//komodod', '-ac_name='+ac_name, '-ac_reward=100000000000', '-conf=' + sys.path[0] + '/node_' + str(i) + "/" + ac_name + ".conf", - '-rpcport=' + str(7000 + i), '-port=' + str(6000 + i), '-datadir=' + sys.path[0] + '/node_' + str(i), - '-ac_supply=10000000000', '-ac_cc=2', '-pubkey=' + test_pubkey, '-whitelist=127.0.0.1'] - if chain_start_mode == 'REGTEST': - start_args.append('-regtest') - start_args.append('-daemon') - else: - start_args.append('-daemon') - subprocess.call(start_args) - time.sleep(5) - else: - start_args = ['../../../src//komodod', '-ac_name='+ac_name, '-ac_reward=100000000000', '-conf=' + sys.path[0] + '/node_' + str(i) + "/" + ac_name + ".conf", - '-rpcport=' + str(7000 + i), '-port=' + str(6000 + i), '-datadir=' + sys.path[0] + '/node_' + str(i), - '-ac_supply=10000000000', '-ac_cc=2', '-addnode=127.0.0.1:6000', '-whitelist=127.0.0.1', '-listen=0', '-pubkey='+test_pubkey] - if i == 1: - start_args.append('-pubkey=' + test_pubkey2) - if chain_start_mode == 'REGTEST': - start_args.append('-regtest') - start_args.append('-daemon') - else: - start_args.append('-daemon') - subprocess.call(start_args) - time.sleep(5) - - -# creating rpc proxies for all nodes -for i in range(clients_to_start): - rpcport = 7000 + i - globals()['proxy_%s' % i] = Proxy("http://%s:%s@127.0.0.1:%d"%("test", "test", int(rpcport))) -time.sleep(2) - - -# checking if proxies works as expected -for i in range(clients_to_start): - while True: - try: - getinfo_output = globals()['proxy_%s' % i].getinfo() - print(getinfo_output) - break - except Exception as e: - print(e) - time.sleep(2) - -# in case of bootstrap checking also if blocksamount > 100 -if is_boostrap_needed == "True": - assert proxy_0.getinfo()["blocks"] > 100 - assert proxy_1.getinfo()["blocks"] > 100 - assert proxy_0.getinfo()["blocks"] == proxy_1.getinfo()["blocks"] - - -# importing privkeys -print("IMPORTING PRIVKEYS") -print(proxy_0.importprivkey(test_wif, "", True)) -print(proxy_1.importprivkey(test_wif2, "", True)) -# ensuring that node1 got premine and some balance -assert proxy_0.getbalance() > 777 - -# checking if test addys belongs to relevant nodes wallets -assert proxy_0.validateaddress(test_address)["ismine"] == True -assert proxy_1.validateaddress(test_address2)["ismine"] == True - -# checking if pubkeys set properly -assert proxy_0.getinfo()["pubkey"] == test_pubkey -assert proxy_1.getinfo()["pubkey"] == test_pubkey2 - -# starting blocks creation on second node, mining rewards will get first public node because of pubkey param -if chain_start_mode == 'REGTEST': - while True: - if int(os.environ['CLIENTS']) > 1: - proxy_1.generate(1) - time.sleep(5) - else: - proxy_0.generate(1) - time.sleep(5) -else: - if int(os.environ['CLIENTS']) > 1: - print("Starting mining on node 2") - proxy_1.setgenerate(True, 1) - # just to ensure better mempool propagation - print("Starting mining on node 1") - proxy_0.setgenerate(True, 1) - else: - print("Starting mining on node 1") - proxy_0.setgenerate(True, 1) - -# TODO: just to prepare a boostrap if needed -# while True: -# blocks_amount = proxy_0.getinfo()["blocks"] -# if blocks_amount == 130: -# balance = proxy_0.getbalance() -# tx_id = proxy_0.sendtoaddress(test_address, balance - 0.1) -# elif blocks_amount > 130: -# print("Finished with blocks pre-generation") -# proxy_0.stop() -# proxy_1.stop() -# time.sleep(2) -# sys.exit() -# else: -# print(proxy_0.getinfo()["blocks"]) -# time.sleep(5) diff --git a/qa/rpc-tests/cc_pytest/test_channels.py b/qa/rpc-tests/cc_pytest/test_channels.py deleted file mode 100644 index 28e8a50b5ac..00000000000 --- a/qa/rpc-tests/cc_pytest/test_channels.py +++ /dev/null @@ -1,232 +0,0 @@ -#!/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. - -import pytest -import json -import time - -from util import assert_success, assert_error, check_if_mined, send_and_mine, rpc_connect, wait_some_blocks, generate_random_string - - -def test_channels(): - - # test params inits - with open('test_config.json', 'r') as f: - params_dict = json.load(f) - - node1_params = params_dict["node1"] - node2_params = params_dict["node2"] - - rpc = rpc_connect(node1_params["rpc_user"], node1_params["rpc_password"], node1_params["rpc_ip"], node1_params["rpc_port"]) - rpc1 = rpc_connect(node2_params["rpc_user"], node2_params["rpc_password"], node2_params["rpc_ip"], node2_params["rpc_port"]) - pubkey = node1_params["pubkey"] - pubkey1 = node2_params["pubkey"] - - is_fresh_chain = params_dict["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 == True - - # have to check that second node have coins to cover txfee at least - rpc.sendtoaddress(rpc1.getnewaddress(), 1) - 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 == True - - # 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 -# time.sleep(5) -# 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 = True -# assert secret_not_revealed == True - -# # 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" diff --git a/qa/rpc-tests/cc_pytest/test_config.json b/qa/rpc-tests/cc_pytest/test_config.json deleted file mode 100644 index a282544265f..00000000000 --- a/qa/rpc-tests/cc_pytest/test_config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "node1" : { - "rpc_user" : "test", - "rpc_password" : "test", - "rpc_ip" : "127.0.0.1", - "rpc_port": 7000, - "pubkey" : "02f0ec2d3da51b09e4fc8d9ba334c275b02b3ab6f22ce7be0ea5059cbccbd1b8c7" - }, - "node2" : { - "rpc_user" : "test", - "rpc_password" : "test", - "rpc_ip" : "127.0.0.1" , - "rpc_port": 7001, - "pubkey" : "0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149" - }, - "is_fresh_chain" : true -} \ No newline at end of file diff --git a/qa/rpc-tests/cc_pytest/test_dice.py b/qa/rpc-tests/cc_pytest/test_dice.py deleted file mode 100644 index b7f48bd3ff0..00000000000 --- a/qa/rpc-tests/cc_pytest/test_dice.py +++ /dev/null @@ -1,194 +0,0 @@ -#!/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. - -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 - - -def test_dice(): - - # test params inits - with open('test_config.json', 'r') as f: - params_dict = json.load(f) - - node1_params = params_dict["node1"] - node2_params = params_dict["node2"] - - rpc = rpc_connect(node1_params["rpc_user"], node1_params["rpc_password"], node1_params["rpc_ip"], node1_params["rpc_port"]) - rpc1 = rpc_connect(node2_params["rpc_user"], node2_params["rpc_password"], node2_params["rpc_ip"], node2_params["rpc_port"]) - pubkey = node1_params["pubkey"] - pubkey1 = node2_params["pubkey"] - - is_fresh_chain = params_dict["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']))) \ No newline at end of file diff --git a/qa/rpc-tests/cc_pytest/test_faucet.py b/qa/rpc-tests/cc_pytest/test_faucet.py deleted file mode 100644 index a0dde45a6d4..00000000000 --- a/qa/rpc-tests/cc_pytest/test_faucet.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/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. - -import pytest -import json - -from util import assert_success, assert_error, check_if_mined, send_and_mine, rpc_connect - -@pytest.mark.first -def test_faucet(): - - # test params inits - with open('test_config.json', 'r') as f: - params_dict = json.load(f) - - node1_params = params_dict["node1"] - node2_params = params_dict["node2"] - - rpc = rpc_connect(node1_params["rpc_user"], node1_params["rpc_password"], node1_params["rpc_ip"], node1_params["rpc_port"]) - rpc1 = rpc_connect(node2_params["rpc_user"], node2_params["rpc_password"], node2_params["rpc_ip"], node2_params["rpc_port"]) - pubkey = node1_params["pubkey"] - pubkey1 = node2_params["pubkey"] - - is_fresh_chain = params_dict["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' - - # 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 \ No newline at end of file diff --git a/qa/rpc-tests/cc_pytest/test_heir.py b/qa/rpc-tests/cc_pytest/test_heir.py deleted file mode 100644 index 4b163e7b367..00000000000 --- a/qa/rpc-tests/cc_pytest/test_heir.py +++ /dev/null @@ -1,153 +0,0 @@ -#!/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. - -import pytest -import time -import json - -from util import assert_success, assert_error, check_if_mined, send_and_mine, rpc_connect, wait_some_blocks - - -def test_heir(): - - # test params inits - with open('test_config.json', 'r') as f: - params_dict = json.load(f) - - node1_params = params_dict["node1"] - node2_params = params_dict["node2"] - - rpc = rpc_connect(node1_params["rpc_user"], node1_params["rpc_password"], node1_params["rpc_ip"], node1_params["rpc_port"]) - rpc1 = rpc_connect(node2_params["rpc_user"], node2_params["rpc_password"], node2_params["rpc_ip"], node2_params["rpc_port"]) - pubkey = node1_params["pubkey"] - pubkey1 = node2_params["pubkey"] - is_fresh_chain = params_dict["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 11 seconds to be sure that needed time passed for heir claiming - time.sleep(11) - 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) - 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" diff --git a/qa/rpc-tests/cc_pytest/test_oracles.py b/qa/rpc-tests/cc_pytest/test_oracles.py deleted file mode 100644 index e7a7ae3bc4d..00000000000 --- a/qa/rpc-tests/cc_pytest/test_oracles.py +++ /dev/null @@ -1,289 +0,0 @@ -#!/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. - -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 - - -def test_oracles(): - - # test params inits - with open('test_config.json', 'r') as f: - params_dict = json.load(f) - - node1_params = params_dict["node1"] - node2_params = params_dict["node2"] - - rpc = rpc_connect(node1_params["rpc_user"], node1_params["rpc_password"], node1_params["rpc_ip"], node1_params["rpc_port"]) - rpc1 = rpc_connect(node2_params["rpc_user"], node2_params["rpc_password"], node2_params["rpc_ip"], node2_params["rpc_port"]) - pubkey = node1_params["pubkey"] - pubkey1 = node2_params["pubkey"] - - is_fresh_chain = params_dict["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())) - 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']) - - wait_some_blocks(rpc, 1) - - for f in valid_formats: - # trying to register with negative datafee - result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "-100") - assert_error(result) - - # trying to register with zero datafee - result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "0") - assert_error(result) - - # trying to register with datafee less than txfee - result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "500") - assert_error(result) - - # 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"]) - assert fund_txid, "got txid" - - wait_some_blocks(rpc, 1) - - for f in valid_formats: - # trying to register valid (funded) - result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "10000") - print(f) - assert_success(result) - 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']) diff --git a/qa/rpc-tests/cc_pytest/test_rewards.py b/qa/rpc-tests/cc_pytest/test_rewards.py deleted file mode 100644 index 82d2cb22d7b..00000000000 --- a/qa/rpc-tests/cc_pytest/test_rewards.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/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. - -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 - - -def test_faucet(): - - # test params inits - with open('test_config.json', 'r') as f: - params_dict = json.load(f) - - node1_params = params_dict["node1"] - node2_params = params_dict["node2"] - - rpc = rpc_connect(node1_params["rpc_user"], node1_params["rpc_password"], node1_params["rpc_ip"], node1_params["rpc_port"]) - rpc1 = rpc_connect(node2_params["rpc_user"], node2_params["rpc_password"], node2_params["rpc_ip"], node2_params["rpc_port"]) - pubkey = node1_params["pubkey"] - pubkey1 = node2_params["pubkey"] - - is_fresh_chain = params_dict["is_fresh_chain"] - - 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) \ No newline at end of file diff --git a/qa/rpc-tests/cc_pytest/test_token.py b/qa/rpc-tests/cc_pytest/test_token.py deleted file mode 100644 index f92191aeeaa..00000000000 --- a/qa/rpc-tests/cc_pytest/test_token.py +++ /dev/null @@ -1,256 +0,0 @@ -#!/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. - -import pytest -import json - -from util import assert_success, assert_error, check_if_mined, send_and_mine, rpc_connect, wait_some_blocks - - -def test_faucet(): - - # test params inits - with open('test_config.json', 'r') as f: - params_dict = json.load(f) - - node1_params = params_dict["node1"] - node2_params = params_dict["node2"] - - rpc = rpc_connect(node1_params["rpc_user"], node1_params["rpc_password"], node1_params["rpc_ip"], node1_params["rpc_port"]) - rpc1 = rpc_connect(node2_params["rpc_user"], node2_params["rpc_password"], node2_params["rpc_ip"], node2_params["rpc_port"]) - pubkey = node1_params["pubkey"] - pubkey1 = node2_params["pubkey"] - - is_fresh_chain = params_dict["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) - 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 diff --git a/qa/rpc-tests/cc_pytest/util.py b/qa/rpc-tests/cc_pytest/util.py deleted file mode 100644 index dcca087e141..00000000000 --- a/qa/rpc-tests/cc_pytest/util.py +++ /dev/null @@ -1,67 +0,0 @@ -import pytest -import time -import sys -from random import choice -from string import ascii_uppercase -from slickrpc import Proxy - - -def assert_success(result): - assert result['result'] == 'success' - - -def assert_error(result): - assert result['result'] == 'error' - - -def check_if_mined(rpc_connection, txid): - attempts = 0 - while True: - try: - confirmations_amount = rpc_connection.getrawtransaction(txid, 1)["confirmations"] - break - except Exception as e: - print(e, file=sys.stderr) - print("tx is in mempool still probably, let's wait a little bit more", file=sys.stderr) - time.sleep(5) - attempts = attempts + 1 - if attempts < 100: - pass - else: - print("waited too long - probably tx stuck by some reason") - if confirmations_amount < 2: - print("tx is not confirmed yet! Let's wait a little more", file=sys.stderr) - time.sleep(5) - - -def send_and_mine(tx_hex, rpc_connection): - txid = rpc_connection.sendrawtransaction(tx_hex) - assert txid, 'got txid' - # we need the tx above to be confirmed in the next block - check_if_mined(rpc_connection, txid) - return txid - - -def rpc_connect(rpc_user, rpc_password, ip, port): - try: - rpc_connection = Proxy("http://%s:%s@%s:%d"%(rpc_user, rpc_password, ip, port)) - except Exception: - raise Exception("Connection error! Probably no daemon on selected port.") - return rpc_connection - - -def wait_some_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: - break - - -def generate_random_string(length): - random_string = ''.join(choice(ascii_uppercase) for i in range(length)) - return random_string From c37875d5fc30d7ef67d1a4a07b759da557d18e1e Mon Sep 17 00:00:00 2001 From: SirSevenG <44422309+SirSevenG@users.noreply.github.com> Date: Fri, 20 Dec 2019 20:36:22 +0700 Subject: [PATCH 4/9] clearer jobs naming --- .github/workflows/komodod_ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/komodod_ci.yml b/.github/workflows/komodod_ci.yml index 15e1c648d64..72ccd1378a3 100644 --- a/.github/workflows/komodod_ci.yml +++ b/.github/workflows/komodod_ci.yml @@ -67,15 +67,15 @@ jobs: # if: runner.os == 'Linux' || runner.os == 'macOS' - linux-test-maincc: - name: Test (Linux/mainCC) + linux-test-dice-token-reards-faucet-cc: + name: Test (Linux/Dice, Token, Faucet, Rewards) runs-on: ubuntu-latest needs: linux-build steps: - uses: actions/checkout@v1 - - name: Install deps (mainCC) + - name: Install deps (Dice, Token, Faucet, Rewards CC) run: | sudo apt-get update sudo apt-get install -q \ @@ -94,7 +94,7 @@ jobs: with: name: komodo-linux - - name: Test (Linux) + - name: Test CC (Linux) run: | mv komodo-linux/komodo-linux.tar.gz . mkdir -p src From 8d6de896bac76e2162686bd002f6765559d36aa3 Mon Sep 17 00:00:00 2001 From: SirSevenG <44422309+SirSevenG@users.noreply.github.com> Date: Fri, 20 Dec 2019 20:43:42 +0700 Subject: [PATCH 5/9] fix new tests path --- .github/workflows/komodod_ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/komodod_ci.yml b/.github/workflows/komodod_ci.yml index 72ccd1378a3..d1642dbb047 100644 --- a/.github/workflows/komodod_ci.yml +++ b/.github/workflows/komodod_ci.yml @@ -100,7 +100,7 @@ jobs: mkdir -p src tar xzvf komodo-linux.tar.gz ./zcutil/fetch-params.sh - cd qa/rpc-tests/pytest_rpc/ + 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: @@ -136,7 +136,7 @@ jobs: mkdir -p src tar xzvf komodo-linux.tar.gz ./zcutil/fetch-params.sh - cd qa/rpc-tests/pytest_rpc/ + cd qa/pytest_komodo ./ci_setup.sh cc_modules/test_oracles.py linux-test-baserpc: @@ -172,7 +172,7 @@ jobs: mkdir -p src tar xzvf komodo-linux.tar.gz ./zcutil/fetch-params.sh - cd qa/rpc-tests/pytest_rpc/ + cd qa/pytest_komodo ./ci_setup.sh basic linux-test-channels: @@ -208,7 +208,7 @@ jobs: mkdir -p src tar xzvf komodo-linux.tar.gz ./zcutil/fetch-params.sh - cd qa/rpc-tests/pytest_rpc/ + cd qa/pytest_komodo ./ci_setup.sh cc_modules/test_channels.py linux-test-heir: @@ -244,7 +244,7 @@ jobs: mkdir -p src tar xzvf komodo-linux.tar.gz ./zcutil/fetch-params.sh - cd qa/rpc-tests/pytest_rpc/ + cd qa/pytest_komodo ./ci_setup.sh cc_modules/test_heir.py windows-build: From 89c154e995ec5c15283bb69ff7ca4f236a4fa9cb Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Wed, 25 Dec 2019 18:13:51 +0700 Subject: [PATCH 6/9] update bootstrap link, update tests --- qa/pytest_komodo/basic/pytest_util.py | 2 + qa/pytest_komodo/basic/test_blocks.py | 15 +++--- qa/pytest_komodo/basic/test_shielded.py | 4 +- qa/pytest_komodo/basic/test_wallet.py | 4 +- qa/pytest_komodo/chainstart.py | 3 +- qa/pytest_komodo/ci_setup.sh | 2 +- qa/pytest_komodo/helper.py | 70 ------------------------- qa/pytest_komodo/nodesconfig.json | 4 +- qa/pytest_komodo/start_ci.bat | 2 +- 9 files changed, 19 insertions(+), 87 deletions(-) delete mode 100644 qa/pytest_komodo/helper.py diff --git a/qa/pytest_komodo/basic/pytest_util.py b/qa/pytest_komodo/basic/pytest_util.py index da644c6c018..c204b300826 100644 --- a/qa/pytest_komodo/basic/pytest_util.py +++ b/qa/pytest_komodo/basic/pytest_util.py @@ -36,6 +36,8 @@ def validate_proxy(env_params_dictionary, proxy, node=0): print(res) assert proxy.validateaddress(env_params_dictionary.get('test_address')[node])['ismine'] assert proxy.getinfo()['pubkey'] == env_params_dictionary.get('test_pubkey')[node] + assert proxy.verifychain() + time.sleep(15) assert proxy.getbalance() > 777 diff --git a/qa/pytest_komodo/basic/test_blocks.py b/qa/pytest_komodo/basic/test_blocks.py index 75aba1b8992..4117421930a 100644 --- a/qa/pytest_komodo/basic/test_blocks.py +++ b/qa/pytest_komodo/basic/test_blocks.py @@ -37,9 +37,6 @@ def test_getbestblockhash(self, test_params): assert isinstance(res, str) def test_getblock(self, test_params): - test_values = { - 'block15': '15' - } schema = { 'type': 'object', 'properties': { @@ -81,12 +78,13 @@ def test_getblock(self, test_params): 'required': ['last_notarized_height', 'hash', 'confirmations', 'rawconfirmations', 'size', 'height', 'version', 'merkleroot', 'segid', 'finalsaplingroot', 'tx', 'time', 'nonce', 'solution', 'bits', 'difficulty', 'chainwork', 'anchor', 'blocktype', 'valuePools', - 'previousblockhash', 'nextblockhash'] + 'previousblockhash'] } rpc = test_params.get('node1').get('rpc') - res = rpc.getblock(test_values['block15']) + blocknum = str(rpc.getblockcount()) + res = rpc.getblock(blocknum) validate_template(res, schema) - res = rpc.getblock(test_values['block15'], False) + res = rpc.getblock(blocknum, False) assert isinstance(res, str) def test_getblockchaininfo(self, test_params): @@ -216,7 +214,7 @@ def test_getchaintxstats(self, test_params): res = rpc.getchaintxstats() validate_template(res, schema) res = rpc.getinfo() - nblocks = (int(res.get('blocks')) - 100) + nblocks = (int(res.get('blocks') / 2)) blockhash = rpc.getblockhash(res.get('blocks')) res = rpc.getchaintxstats(nblocks) validate_template(res, schema) @@ -279,7 +277,8 @@ def test_gettxout(self, test_params): rpc = test_params.get('node1').get('rpc') res = rpc.listunspent() txid = res[0].get('txid') - res = rpc.gettxout(txid, 0) + vout = res[0].get('vout') + res = rpc.gettxout(txid, vout) validate_template(res, schema) res = rpc.gettxout(txid, -1) assert not res # gettxout retuns None when vout does not exist diff --git a/qa/pytest_komodo/basic/test_shielded.py b/qa/pytest_komodo/basic/test_shielded.py index 6b86542d7c6..d943eee8405 100644 --- a/qa/pytest_komodo/basic/test_shielded.py +++ b/qa/pytest_komodo/basic/test_shielded.py @@ -84,8 +84,8 @@ def test_z_send(self, test_params): shielded1 = rpc1.z_getnewaddress() transparent2 = rpc2.getnewaddress() shielded2 = rpc2.z_getnewaddress() - amount1 = rpc1.getbalance() / 100 - amount2 = amount1 / 10 + amount1 = float("{0:.8f}".format(rpc1.listunspent()[-1].get('amount') / 10)) + amount2 = float("{0:.8f}".format(amount1 / 10)) try: import slickrpc authproxy = 0 diff --git a/qa/pytest_komodo/basic/test_wallet.py b/qa/pytest_komodo/basic/test_wallet.py index 32af032c8c8..1058ef4b309 100644 --- a/qa/pytest_komodo/basic/test_wallet.py +++ b/qa/pytest_komodo/basic/test_wallet.py @@ -309,7 +309,7 @@ def test_sendtoaddress(self, test_params): # python float() is double precision floating point number, # where sendmany expects regural float (8 digits) value # "{0:.8f}".format(value)) returns number string with 8 digit precision and float() corrects the type - amount = float("{0:.8f}".format(rpc.getbalance() / 1000)) + amount = float("{0:.8f}".format(rpc.listunspent()[-1].get('amount') / 10)) txid = rpc.sendtoaddress(addr, amount) assert isinstance(txid, str) # wait tx to be confirmed @@ -333,7 +333,7 @@ def test_sendmany(self, test_params): address1 = rpc1.getnewaddress() address2 = rpc2.getnewaddress() # clarification in test_sendtoaddress above - amount = float("{0:.8f}".format(rpc1.getbalance() / 1000)) # float("{0:.8f}".format(amount2)) + amount = float("{0:.8f}".format(rpc1.listunspent()[-1].get('amount') / 10)) # float("{0:.8f}".format(amount2)) send = {address1: amount, address2: amount} txid = rpc1.sendmany("", send) assert isinstance(txid, str) diff --git a/qa/pytest_komodo/chainstart.py b/qa/pytest_komodo/chainstart.py index bdeadcff1c4..c4bdd397b6d 100644 --- a/qa/pytest_komodo/chainstart.py +++ b/qa/pytest_komodo/chainstart.py @@ -119,6 +119,7 @@ def main(): else: cl_args.append('-ac_cc=2') cl_args.extend(ac_params.get('daemon_params')) + print(cl_args) if os.name == "posix": subprocess.call(cl_args) else: @@ -132,8 +133,8 @@ def main(): 'rpc_port': 7000 + i } rpc_p = create_proxy(node_params) - validate_proxy(env_params, rpc_p, i) enable_mining(rpc_p) + validate_proxy(env_params, rpc_p, i) if __name__ == '__main__': diff --git a/qa/pytest_komodo/ci_setup.sh b/qa/pytest_komodo/ci_setup.sh index cdd39412770..0fb5807a960 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="http://159.69.45.70/bootstrap.tar.gz" +export BOOTSTRAP_URL="https://sirseven.me/share/bootstrap.tar.gz" # starting the chains python3 chainstart.py diff --git a/qa/pytest_komodo/helper.py b/qa/pytest_komodo/helper.py deleted file mode 100644 index 72bb17ade19..00000000000 --- a/qa/pytest_komodo/helper.py +++ /dev/null @@ -1,70 +0,0 @@ -import os -import time -from decimal import * -from basic.pytest_util import validate_template -if os.name == 'posix': - from slickrpc import Proxy -else: - from bitcoinrpc.authproxy import AuthServiceProxy as Proxy - - -def main(): - node_params_dictionary1 = { - "rpc_user": "test", - "rpc_password": "test", - "rpc_ip": "127.0.0.1", - "rpc_port": 7000 - } - rpc1 = Proxy("http://%s:%s@%s:%d" % (node_params_dictionary1.get('rpc_user'), - node_params_dictionary1.get('rpc_password'), - node_params_dictionary1.get('rpc_ip'), - node_params_dictionary1.get('rpc_port'))) - - node_params_dictionary2 = { - "rpc_user": "test", - "rpc_password": "test", - "rpc_ip": "127.0.0.1", - "rpc_port": 7001 - } - rpc2 = Proxy("http://%s:%s@%s:%d" % (node_params_dictionary2.get('rpc_user'), - node_params_dictionary2.get('rpc_password'), - node_params_dictionary2.get('rpc_ip'), - node_params_dictionary2.get('rpc_port'))) - - #rpc1.setgenerate(True, 1) - #rpc2.setgenerate(True, 1) - #transparent1 = rpc1.getnewaddress() - #print(transparent1) - #shielded1 = rpc1.z_getnewaddress() - #print(shielded1) - #transparent2 = rpc2.getnewaddress() - #print(transparent2) - #shielded2 = rpc2.z_getnewaddress() - #print(shielded2) - #res = rpc1.z_gettotalbalance() - #print(res) - #res = rpc1.z_getbalance(shielded1) - #print(res) - #res = rpc1.getinfo().get("synced") - #print(res) - #res = rpc2.getinfo().get("synced") - #print(res) - #res = rpc1.listunspent() - #print(res) - #res = rpc2.z_listunspent() - #print(res) - #amount = rpc1.getbalance() / 1000 - #print(amount) - #t_send = [{'address': 'zs10h8kdr3r98rkekfhn3za7mu4vjgpe4h96mwqk3ww2pt33n7jjzktrwhuksxqqd2ztg2awj9y8cp', - # 'amount': '55,11'}] - ##z_send = [{'address': shielded2, 'amount': amount}] - #opid = rpc1.z_sendmany('RBvTN4GT9nVhH7BbJV2MYkfFLSwQvTA17H', t_send) - ##print(opid) - #res = rpc1.z_getoperationstatus([opid]) - #print(res) - rpc1.stop() - rpc2.stop() - - -if __name__ == '__main__': - main() diff --git a/qa/pytest_komodo/nodesconfig.json b/qa/pytest_komodo/nodesconfig.json index 10ba3e45e46..cd534adda14 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": "64b5e5151f027095803e4a8d98d66e8d2777f54321b232ece84d364a046606fb" + "txid": "e9945094eb1a9028afd310719aea21966425ceccc3f8c0972277a96201ca1b81" }, "node2" : { "rpc_user" : "test", @@ -17,7 +17,7 @@ "net_port": 6001, "pubkey" : "0285f68aec0e2f8b5e817d71a2a20a1fda74ea9943c752a13136a3a30fa49c0149", "address": "RHoTHYiHD8TU4k9rbY4Aoj3ztxUARMJikH", - "txid": "79d6b61ab663579d3682747b82f1118c1678e1759ccbd6749b67905572681bfb" + "txid": "3376a48a7daf543d8401e072102d4e93f53f300a101bd67e82820d2da0f2729e" }, "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 9aac73072aa..ad430fd23d5 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=http://159.69.45.70/bootstrap.tar.gz +set BOOTSTRAP_URL=https://sirseven.me/share/bootstrap.tar.gz python.exe chainstart.py From ca37bb77640c8cf9c97c0760fbd6fd15d1e2a8f4 Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Sun, 29 Dec 2019 19:54:23 +0700 Subject: [PATCH 7/9] update oraclesCC test, minor improvements --- qa/pytest_komodo/basic/pytest_util.py | 16 +++++++++-- qa/pytest_komodo/basic/test_wallet.py | 30 +++------------------ qa/pytest_komodo/cc_modules/test_oracles.py | 25 ++++++++++++----- 3 files changed, 35 insertions(+), 36 deletions(-) diff --git a/qa/pytest_komodo/basic/pytest_util.py b/qa/pytest_komodo/basic/pytest_util.py index c204b300826..7e8c65a3d88 100644 --- a/qa/pytest_komodo/basic/pytest_util.py +++ b/qa/pytest_komodo/basic/pytest_util.py @@ -3,8 +3,10 @@ import os if os.name == 'posix': from slickrpc import Proxy + from slickrpc.exc import RpcException as RPCError else: from bitcoinrpc.authproxy import AuthServiceProxy as Proxy + from bitcoinrpc.authproxy import JSONRPCException as RPCError def create_proxy(node_params_dictionary): @@ -47,7 +49,17 @@ def enable_mining(proxy): threads_count = cores - 2 else: threads_count = 1 - proxy.setgenerate(True, threads_count) + tries = 0 + while True: + try: + proxy.setgenerate(True, threads_count) + break + except RPCError 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): # should be used after tx is send @@ -57,7 +69,7 @@ def mine_and_waitconfirms(txid, proxy): # should be used after tx is send try: confirmations_amount = proxy.getrawtransaction(txid, 1)['confirmations'] break - except Exception as e: + 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 diff --git a/qa/pytest_komodo/basic/test_wallet.py b/qa/pytest_komodo/basic/test_wallet.py index 1058ef4b309..2da614cdb2d 100644 --- a/qa/pytest_komodo/basic/test_wallet.py +++ b/qa/pytest_komodo/basic/test_wallet.py @@ -7,7 +7,7 @@ import os import time from decimal import * -from pytest_util import validate_template +from pytest_util import validate_template, mine_and_waitconfirms @pytest.mark.usefixtures("proxy_connection") @@ -313,19 +313,7 @@ def test_sendtoaddress(self, test_params): txid = rpc.sendtoaddress(addr, amount) assert isinstance(txid, str) # wait tx to be confirmed - attempts = 0 - while True: - print('waiting tx to be confirmed\n') - confs = rpc.getrawtransaction(txid, 1).get('confirmations') - if confs: - if confs > 1: - print("TX confirmed\n") - break - if attempts > 100: - return False - else: - attempts += 1 - time.sleep(10) + mine_and_waitconfirms(txid, rpc) def test_sendmany(self, test_params): rpc1 = test_params.get('node1').get('rpc') @@ -338,19 +326,7 @@ def test_sendmany(self, test_params): txid = rpc1.sendmany("", send) assert isinstance(txid, str) # wait tx to be confirmed - attempts = 0 - while True: - print('waiting tx to be confirmed\n') - confs = rpc1.getrawtransaction(txid, 1).get('confirmations') - if confs: - if confs > 1: - print("TX confirmed\n") - break - if attempts > 100: - return False - else: - attempts += 1 - time.sleep(10) + mine_and_waitconfirms(txid, rpc1) def test_setupkey(self, test_params): schema = { diff --git a/qa/pytest_komodo/cc_modules/test_oracles.py b/qa/pytest_komodo/cc_modules/test_oracles.py index b4003c72062..df262e3c97b 100644 --- a/qa/pytest_komodo/cc_modules/test_oracles.py +++ b/qa/pytest_komodo/cc_modules/test_oracles.py @@ -5,7 +5,7 @@ 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 @@ -67,10 +67,10 @@ def test_oracles(test_params): for f in valid_formats: result = rpc.oraclescreate("Test_" + f, "Test_" + f, f) assert_success(result) - globals()["oracle_{}".format(f)] = rpc.sendrawtransaction(result['hex']) - - wait_some_blocks(rpc, 1) + # 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: # trying to register with negative datafee result = rpc.oraclesregister(globals()["oracle_{}".format(f)], "-100") @@ -92,15 +92,26 @@ def test_oracles(test_params): 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, 1) + 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)], "10000") - print(f) + 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" From 616acdc868f19d31de009c36059893de9ec84c9a Mon Sep 17 00:00:00 2001 From: SirSevenG <44422309+SirSevenG@users.noreply.github.com> Date: Sun, 29 Dec 2019 20:23:51 +0700 Subject: [PATCH 8/9] apt remove php-apcu Remove apt packages with broken links before updates --- .github/workflows/komodod_ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/komodod_ci.yml b/.github/workflows/komodod_ci.yml index d1642dbb047..70ffcca669e 100644 --- a/.github/workflows/komodod_ci.yml +++ b/.github/workflows/komodod_ci.yml @@ -13,7 +13,7 @@ jobs: - name: Install deps (Linux) if: runner.os == 'Linux' run: | - sudo apt-get remove php7.1-fpm php7.2-fpm php7.3-fpm + sudo apt-get remove php7.1-fpm php7.2-fpm php7.3-fpm php-apcu sudo apt-get update sudo apt-get upgrade -y sudo apt-get update @@ -259,7 +259,7 @@ jobs: DEBIAN_FRONTEND: noninteractive if: runner.os == 'Linux' run: | - sudo apt-get remove php5.6-fpm php7.0-fpm php7.1-fpm php7.2-fpm php7.3-fpm + sudo apt-get remove php5.6-fpm php7.0-fpm php7.1-fpm php7.2-fpm php7.3-fpm php-apcu 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 git python zlib1g-dev wget 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 libsodium-dev -y From 8eb9741fb638963264a4bf3341d02aef57d9125c Mon Sep 17 00:00:00 2001 From: SirSevenG Date: Mon, 13 Jan 2020 18:56:35 +0700 Subject: [PATCH 9/9] Mine oracles creation in separate blocks better mine method exception handling --- qa/pytest_komodo/basic/pytest_util.py | 8 ++++--- qa/pytest_komodo/cc_modules/test_channels.py | 8 +++---- qa/pytest_komodo/cc_modules/test_rewards.py | 1 - qa/pytest_komodo/cc_modules/util.py | 5 ++-- qa/pytest_komodo/chainconfig.json | 3 ++- qa/pytest_komodo/chainstart.py | 25 ++++++++------------ 6 files changed, 23 insertions(+), 27 deletions(-) diff --git a/qa/pytest_komodo/basic/pytest_util.py b/qa/pytest_komodo/basic/pytest_util.py index 7e8c65a3d88..04a3df66772 100644 --- a/qa/pytest_komodo/basic/pytest_util.py +++ b/qa/pytest_komodo/basic/pytest_util.py @@ -1,12 +1,14 @@ import time import jsonschema import os -if os.name == 'posix': +try: from slickrpc import Proxy from slickrpc.exc import RpcException as RPCError -else: + from pycurl import error as HttpError +except ImportError: 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): @@ -54,7 +56,7 @@ def enable_mining(proxy): try: proxy.setgenerate(True, threads_count) break - except RPCError as e: + except (RPCError, HttpError) as e: print(e, " Waiting chain startup\n") time.sleep(10) tries += 1 diff --git a/qa/pytest_komodo/cc_modules/test_channels.py b/qa/pytest_komodo/cc_modules/test_channels.py index c67ba6587ac..fd72b2139f0 100644 --- a/qa/pytest_komodo/cc_modules/test_channels.py +++ b/qa/pytest_komodo/cc_modules/test_channels.py @@ -115,7 +115,7 @@ def test_channels(test_params): assert result == 200000 result = rpc1.validateaddress(raw_transaction["vout"][3]["scriptPubKey"]["addresses"][0])["ismine"] - assert result == True + assert result # have to check that second node have coins to cover txfee at least rpc.sendtoaddress(rpc1.getnewaddress(), 1) @@ -163,7 +163,7 @@ def test_channels(test_params): assert result == 700000 result = rpc.validateaddress(raw_transaction["vout"][2]["scriptPubKey"]["addresses"][0])["ismine"] - assert result == True + 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") @@ -218,8 +218,8 @@ def test_channels(test_params): # try: # rpc1.channelsinfo(channel2_txid)["Transactions"][1]["Secret"] # except Exception: -# secret_not_revealed = True -# assert secret_not_revealed == True +# secret_not_revealed +# assert secret_not_revealed # # # trying to initiate payment from second node with revealed secret # assert rpc1.getinfo()["connections"] == 0 diff --git a/qa/pytest_komodo/cc_modules/test_rewards.py b/qa/pytest_komodo/cc_modules/test_rewards.py index 64a9be11ca7..3c2759852bc 100644 --- a/qa/pytest_komodo/cc_modules/test_rewards.py +++ b/qa/pytest_komodo/cc_modules/test_rewards.py @@ -5,7 +5,6 @@ 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 diff --git a/qa/pytest_komodo/cc_modules/util.py b/qa/pytest_komodo/cc_modules/util.py index 28b2ebd3382..eb37fc641dc 100644 --- a/qa/pytest_komodo/cc_modules/util.py +++ b/qa/pytest_komodo/cc_modules/util.py @@ -1,12 +1,11 @@ import pytest import time import sys -import os from random import choice from string import ascii_uppercase -if os.name == 'posix': +try: from slickrpc import Proxy -else: +except ImportError: from bitcoinrpc.authproxy import AuthServiceProxy as Proxy diff --git a/qa/pytest_komodo/chainconfig.json b/qa/pytest_komodo/chainconfig.json index 92b2d7205c8..32775a55379 100644 --- a/qa/pytest_komodo/chainconfig.json +++ b/qa/pytest_komodo/chainconfig.json @@ -4,7 +4,8 @@ "rpc_user": "test", "rpcpassword": "test", "rpcallowip": "0.0.0.0/0", - "rpcport": "7000", + "rpcport": 7000, + "port": 6000, "rpcbind": "0.0.0.0", "ac_reward": "100000000000", "ac_supply": "10000000000", diff --git a/qa/pytest_komodo/chainstart.py b/qa/pytest_komodo/chainstart.py index c4bdd397b6d..fbdf2c8d95b 100644 --- a/qa/pytest_komodo/chainstart.py +++ b/qa/pytest_komodo/chainstart.py @@ -99,25 +99,20 @@ def main(): cl_args = [ac_params.get('binary_path'), '-ac_name=' + aschain, '-conf=' + confpath, - '-rpcport=' + str(7000 + i), - '-port=' + str(6000 + i), '-datadir=' + datapath, '-pubkey=' + env_params.get('test_pubkey')[i], ] - if i > 0: - cl_args.append('-addnode=127.0.0.1:6000') - if ac_params.get('ac_reward'): - cl_args.append('-ac_reward=' + ac_params.get('ac_reward')) + if i == 0: + for key in ac_params.keys(): + cl_args.append('-' + key + '=' + str(ac_params.get(key))) else: - cl_args.append('-ac_reward=100000000000') - if ac_params.get('ac_supply'): - cl_args.append('-ac_supply=' + ac_params.get('ac_supply')) - else: - cl_args.append('-ac_supply=10000000000') - if ac_params.get('ac_cc'): - cl_args.append('-ac_cc=' + ac_params.get('ac_cc')) - else: - cl_args.append('-ac_cc=2') + cl_args.append('-addnode=127.0.0.1:' + str(ac_params.get('port'))) + for key in ac_params.keys(): + if isinstance(ac_params.get(key), int): + data = ac_params.get(key) + 1 + cl_args.append('-' + key + '=' + str(data)) + else: + cl_args.append('-' + key + '=' + str(ac_params.get(key))) cl_args.extend(ac_params.get('daemon_params')) print(cl_args) if os.name == "posix":